diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/WebPage')
68 files changed, 13452 insertions, 0 deletions
diff --git a/Source/WebKit2/WebProcess/WebPage/DecoderAdapter.cpp b/Source/WebKit2/WebProcess/WebPage/DecoderAdapter.cpp new file mode 100644 index 000000000..7c93dae7f --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DecoderAdapter.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "DecoderAdapter.h" + +#include "DataReference.h" +#include "WebCoreArgumentCoders.h" + +namespace WebKit { + +DecoderAdapter::DecoderAdapter(const uint8_t* buffer, size_t bufferSize) + : m_decoder(buffer, bufferSize) +{ +} + +bool DecoderAdapter::decodeBytes(Vector<uint8_t>& bytes) +{ + CoreIPC::DataReference dataReference; + if (!m_decoder.decodeVariableLengthByteArray(dataReference)) + return false; + + bytes = dataReference.vector(); + return true; +} + +bool DecoderAdapter::decodeBool(bool& value) +{ + return m_decoder.decodeBool(value); +} + +bool DecoderAdapter::decodeUInt32(uint32_t& value) +{ + return m_decoder.decodeUInt32(value); +} + +bool DecoderAdapter::decodeUInt64(uint64_t& value) +{ + return m_decoder.decodeUInt64(value); +} + +bool DecoderAdapter::decodeInt32(int32_t& value) +{ + return m_decoder.decodeInt32(value); +} + +bool DecoderAdapter::decodeInt64(int64_t& value) +{ + return m_decoder.decodeInt64(value); +} + +bool DecoderAdapter::decodeFloat(float& value) +{ + return m_decoder.decodeFloat(value); +} + +bool DecoderAdapter::decodeDouble(double& value) +{ + return m_decoder.decodeDouble(value); +} + +bool DecoderAdapter::decodeString(String& value) +{ + return m_decoder.decode(value); +} + +} diff --git a/Source/WebKit2/WebProcess/WebPage/DecoderAdapter.h b/Source/WebKit2/WebProcess/WebPage/DecoderAdapter.h new file mode 100644 index 000000000..bd34ea8d3 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DecoderAdapter.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef DecoderAdapter_h +#define DecoderAdapter_h + +#include "ArgumentDecoder.h" +#include <wtf/Decoder.h> +#include <wtf/Forward.h> + +namespace WebKit { + +class DecoderAdapter : public Decoder { +public: + DecoderAdapter(const uint8_t* buffer, size_t bufferSize); + +private: + virtual bool decodeBytes(Vector<uint8_t>&); + virtual bool decodeBool(bool&); + virtual bool decodeUInt32(uint32_t&); + virtual bool decodeUInt64(uint64_t&); + virtual bool decodeInt32(int32_t&); + virtual bool decodeInt64(int64_t&); + virtual bool decodeFloat(float&); + virtual bool decodeDouble(double&); + virtual bool decodeString(String&); + + CoreIPC::ArgumentDecoder m_decoder; +}; + +} // namespace WebKit + +#endif // DecoderAdapter_h diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingArea.cpp b/Source/WebKit2/WebProcess/WebPage/DrawingArea.cpp new file mode 100644 index 000000000..9d42ce4a5 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DrawingArea.cpp @@ -0,0 +1,72 @@ +/* + * 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 "config.h" +#include "DrawingArea.h" + +// Subclasses +#include "DrawingAreaImpl.h" + +#if USE(TILED_BACKING_STORE) +#include "TiledDrawingArea.h" +#endif + +#if PLATFORM(MAC) +#include "TiledCoreAnimationDrawingArea.h" +#endif + +#include "WebPageCreationParameters.h" + +namespace WebKit { + +PassOwnPtr<DrawingArea> DrawingArea::create(WebPage* webPage, const WebPageCreationParameters& parameters) +{ + switch (parameters.drawingAreaType) { + case DrawingAreaTypeImpl: + return DrawingAreaImpl::create(webPage, parameters); +#if USE(TILED_BACKING_STORE) + case DrawingAreaTypeTiled: + return adoptPtr(new TiledDrawingArea(webPage)); +#endif +#if PLATFORM(MAC) + case DrawingAreaTypeTiledCoreAnimation: + return TiledCoreAnimationDrawingArea::create(webPage, parameters); +#endif + } + + return nullptr; +} + +DrawingArea::DrawingArea(DrawingAreaType type, WebPage* webPage) + : m_type(type) + , m_webPage(webPage) +{ +} + +DrawingArea::~DrawingArea() +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingArea.h b/Source/WebKit2/WebProcess/WebPage/DrawingArea.h new file mode 100644 index 000000000..ffbbdbb57 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DrawingArea.h @@ -0,0 +1,122 @@ +/* + * 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. + */ + +#ifndef DrawingArea_h +#define DrawingArea_h + +#include "DrawingAreaInfo.h" +#include <WebCore/FloatPoint.h> +#include <WebCore/IntRect.h> +#include <wtf/Noncopyable.h> +#include <wtf/PassOwnPtr.h> + +namespace CoreIPC { + class ArgumentDecoder; + class Connection; + class MessageID; +} + +namespace WebCore { + class GraphicsLayer; +} + +namespace WebKit { + +class WebPage; +struct WebPageCreationParameters; + +#if PLATFORM(WIN) +struct WindowGeometry; +#endif + +class DrawingArea { + WTF_MAKE_NONCOPYABLE(DrawingArea); + +public: + static PassOwnPtr<DrawingArea> create(WebPage*, const WebPageCreationParameters&); + virtual ~DrawingArea(); + + void didReceiveDrawingAreaMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + + virtual void setNeedsDisplay(const WebCore::IntRect&) = 0; + virtual void scroll(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) = 0; + + // FIXME: These should be pure virtual. + virtual void pageBackgroundTransparencyChanged() { } + virtual void forceRepaint() { } + virtual void setLayerTreeStateIsFrozen(bool) { } + virtual bool layerTreeStateIsFrozen() const { return false; } + + virtual void didInstallPageOverlay() { } + virtual void didUninstallPageOverlay() { } + virtual void setPageOverlayNeedsDisplay(const WebCore::IntRect&) { } + virtual void pageCustomRepresentationChanged() { } + + virtual void setPaintingEnabled(bool) { } + +#if USE(ACCELERATED_COMPOSITING) + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) = 0; + virtual void scheduleCompositingLayerSync() = 0; +#if USE(TEXTURE_MAPPER) + virtual void didReceiveLayerTreeHostMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*) = 0; +#endif +#endif + +#if PLATFORM(WIN) + virtual void scheduleChildWindowGeometryUpdate(const WindowGeometry&) = 0; +#endif + +protected: + DrawingArea(DrawingAreaType, WebPage*); + + DrawingAreaType m_type; + WebPage* m_webPage; + +private: + // CoreIPC message handlers. + // FIXME: These should be pure virtual. + virtual void updateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, float deviceScaleFactor, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset) { } + virtual void didUpdate() { } + virtual void suspendPainting() { } + virtual void resumePainting() { } + +#if PLATFORM(MAC) + // Used by TiledCoreAnimationDrawingArea. + virtual void updateGeometry(const WebCore::IntSize& viewSize) { } +#endif + +#if USE(TILED_BACKING_STORE) + virtual void setSize(const WebCore::IntSize& viewSize) { } + virtual void setVisibleContentRectAndScale(const WebCore::IntRect&, float) { } + virtual void setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint&) { } + virtual void setContentsScale(float scale) { } + virtual void renderNextFrame() { } + virtual void takeSnapshot(const WebCore::IntSize& targetSize, const WebCore::IntRect& contentsRect) { } +#endif +}; + +} // namespace WebKit + +#endif // DrawingArea_h diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingArea.messages.in b/Source/WebKit2/WebProcess/WebPage/DrawingArea.messages.in new file mode 100644 index 000000000..48c3e1ae5 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DrawingArea.messages.in @@ -0,0 +1,42 @@ +# Copyright (C) 2010, 2011 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. + +messages -> DrawingArea { + UpdateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, float deviceScaleFactor, WebCore::IntSize size, WebCore::IntSize scrollOffset) + DidUpdate() + SuspendPainting() + ResumePainting() + PageCustomRepresentationChanged() + +#if PLATFORM(MAC) + // Used by TiledCoreAnimationDrawingArea. + UpdateGeometry(WebCore::IntSize viewSize) +#endif + +#if USE(TILED_BACKING_STORE) + SetSize(WebCore::IntSize viewSize) + SetVisibleContentRectAndScale(WebCore::IntRect visibleContentRect, float scale) + SetVisibleContentRectTrajectoryVector(WebCore::FloatPoint trajectoryVector) + RenderNextFrame() + TakeSnapshot(WebCore::IntSize size, WebCore::IntRect contentsRect) +#endif +} diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp new file mode 100644 index 000000000..e281d3652 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp @@ -0,0 +1,679 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "DrawingAreaImpl.h" + +#include "DrawingAreaProxyMessages.h" +#include "LayerTreeContext.h" +#include "ShareableBitmap.h" +#include "UpdateInfo.h" +#include "WebPage.h" +#include "WebPageCreationParameters.h" +#include "WebProcess.h" +#include <WebCore/GraphicsContext.h> +#include <WebCore/Page.h> +#include <WebCore/Settings.h> + +using namespace WebCore; +using namespace std; + +namespace WebKit { + +PassOwnPtr<DrawingAreaImpl> DrawingAreaImpl::create(WebPage* webPage, const WebPageCreationParameters& parameters) +{ + return adoptPtr(new DrawingAreaImpl(webPage, parameters)); +} + +DrawingAreaImpl::~DrawingAreaImpl() +{ + if (m_layerTreeHost) + m_layerTreeHost->invalidate(); +} + +DrawingAreaImpl::DrawingAreaImpl(WebPage* webPage, const WebPageCreationParameters& parameters) + : DrawingArea(DrawingAreaTypeImpl, webPage) + , m_backingStoreStateID(0) + , m_isPaintingEnabled(true) + , m_inUpdateBackingStoreState(false) + , m_shouldSendDidUpdateBackingStoreState(false) + , m_isWaitingForDidUpdate(false) + , m_compositingAccordingToProxyMessages(false) + , m_layerTreeStateIsFrozen(false) + , m_wantsToExitAcceleratedCompositingMode(false) + , m_isPaintingSuspended(!parameters.isVisible) + , m_alwaysUseCompositing(false) + , m_displayTimer(WebProcess::shared().runLoop(), this, &DrawingAreaImpl::displayTimerFired) + , m_exitCompositingTimer(WebProcess::shared().runLoop(), this, &DrawingAreaImpl::exitAcceleratedCompositingMode) +{ + if (webPage->corePage()->settings()->acceleratedDrawingEnabled()) + m_alwaysUseCompositing = true; + + if (m_alwaysUseCompositing) + enterAcceleratedCompositingMode(0); +} + +void DrawingAreaImpl::setNeedsDisplay(const IntRect& rect) +{ + if (!m_isPaintingEnabled) + return; + + IntRect dirtyRect = rect; + dirtyRect.intersect(m_webPage->bounds()); + + if (dirtyRect.isEmpty()) + return; + + if (m_layerTreeHost) { + ASSERT(m_dirtyRegion.isEmpty()); + + m_layerTreeHost->setNonCompositedContentsNeedDisplay(dirtyRect); + return; + } + + if (m_webPage->mainFrameHasCustomRepresentation()) + return; + + m_dirtyRegion.unite(dirtyRect); + scheduleDisplay(); +} + +void DrawingAreaImpl::scroll(const IntRect& scrollRect, const IntSize& scrollOffset) +{ + if (!m_isPaintingEnabled) + return; + + if (m_layerTreeHost) { + ASSERT(m_scrollRect.isEmpty()); + ASSERT(m_scrollOffset.isEmpty()); + ASSERT(m_dirtyRegion.isEmpty()); + + m_layerTreeHost->scrollNonCompositedContents(scrollRect, scrollOffset); + return; + } + + if (m_webPage->mainFrameHasCustomRepresentation()) + return; + + if (!m_scrollRect.isEmpty() && scrollRect != m_scrollRect) { + unsigned scrollArea = scrollRect.width() * scrollRect.height(); + unsigned currentScrollArea = m_scrollRect.width() * m_scrollRect.height(); + + if (currentScrollArea >= scrollArea) { + // The rect being scrolled is at least as large as the rect we'd like to scroll. + // Go ahead and just invalidate the scroll rect. + setNeedsDisplay(scrollRect); + return; + } + + // Just repaint the entire current scroll rect, we'll scroll the new rect instead. + setNeedsDisplay(m_scrollRect); + m_scrollRect = IntRect(); + m_scrollOffset = IntSize(); + } + + // Get the part of the dirty region that is in the scroll rect. + Region dirtyRegionInScrollRect = intersect(scrollRect, m_dirtyRegion); + if (!dirtyRegionInScrollRect.isEmpty()) { + // There are parts of the dirty region that are inside the scroll rect. + // We need to subtract them from the region, move them and re-add them. + m_dirtyRegion.subtract(scrollRect); + + // Move the dirty parts. + Region movedDirtyRegionInScrollRect = intersect(translate(dirtyRegionInScrollRect, scrollOffset), scrollRect); + + // And add them back. + m_dirtyRegion.unite(movedDirtyRegionInScrollRect); + } + + // Compute the scroll repaint region. + Region scrollRepaintRegion = subtract(scrollRect, translate(scrollRect, scrollOffset)); + + m_dirtyRegion.unite(scrollRepaintRegion); + scheduleDisplay(); + + m_scrollRect = scrollRect; + m_scrollOffset += scrollOffset; +} + +void DrawingAreaImpl::setLayerTreeStateIsFrozen(bool isFrozen) +{ + if (m_layerTreeStateIsFrozen == isFrozen) + return; + + m_layerTreeStateIsFrozen = isFrozen; + + if (m_layerTreeHost) + m_layerTreeHost->setLayerFlushSchedulingEnabled(!isFrozen); + + if (isFrozen) + m_exitCompositingTimer.stop(); + else if (m_wantsToExitAcceleratedCompositingMode) + exitAcceleratedCompositingModeSoon(); +} + +void DrawingAreaImpl::forceRepaint() +{ + setNeedsDisplay(m_webPage->bounds()); + + m_webPage->layoutIfNeeded(); + + if (m_layerTreeHost) { + // FIXME: We need to do the same work as the layerHostDidFlushLayers function here, + // but clearly it doesn't make sense to call the function with that name. + // Consider refactoring and renaming it. + if (m_compositingAccordingToProxyMessages) + m_layerTreeHost->forceRepaint(); + else { + // Call setShouldNotifyAfterNextScheduledLayerFlush(false) here to + // prevent layerHostDidFlushLayers() from being called a second time. + m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false); + layerHostDidFlushLayers(); + } + return; + } + + m_isWaitingForDidUpdate = false; + display(); +} + +void DrawingAreaImpl::didInstallPageOverlay() +{ + if (m_layerTreeHost) + m_layerTreeHost->didInstallPageOverlay(); +} + +void DrawingAreaImpl::didUninstallPageOverlay() +{ + if (m_layerTreeHost) + m_layerTreeHost->didUninstallPageOverlay(); + + setNeedsDisplay(m_webPage->bounds()); +} + +void DrawingAreaImpl::setPageOverlayNeedsDisplay(const IntRect& rect) +{ + if (m_layerTreeHost) { + m_layerTreeHost->setPageOverlayNeedsDisplay(rect); + return; + } + + setNeedsDisplay(rect); +} + +void DrawingAreaImpl::pageCustomRepresentationChanged() +{ + if (!m_alwaysUseCompositing) + return; + + if (m_webPage->mainFrameHasCustomRepresentation()) { + if (m_layerTreeHost) + exitAcceleratedCompositingMode(); + } else if (!m_layerTreeHost) + enterAcceleratedCompositingMode(0); +} + +void DrawingAreaImpl::setPaintingEnabled(bool paintingEnabled) +{ + m_isPaintingEnabled = paintingEnabled; +} + +void DrawingAreaImpl::layerHostDidFlushLayers() +{ + ASSERT(m_layerTreeHost); + + m_layerTreeHost->forceRepaint(); + + if (m_shouldSendDidUpdateBackingStoreState && !exitAcceleratedCompositingModePending()) { + sendDidUpdateBackingStoreState(); + return; + } + + if (!m_layerTreeHost) + return; + +#if USE(ACCELERATED_COMPOSITING) + ASSERT(!m_compositingAccordingToProxyMessages); + if (!exitAcceleratedCompositingModePending()) { + m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(m_backingStoreStateID, m_layerTreeHost->layerTreeContext())); + m_compositingAccordingToProxyMessages = true; + } +#endif +} + +void DrawingAreaImpl::setRootCompositingLayer(GraphicsLayer* graphicsLayer) +{ + // FIXME: Instead of using nested if statements, we should keep a compositing state + // enum in the DrawingAreaImpl object and have a changeAcceleratedCompositingState function + // that takes the new state. + + if (graphicsLayer) { + if (!m_layerTreeHost) { + // We're actually entering accelerated compositing mode. + enterAcceleratedCompositingMode(graphicsLayer); + } else { + // We're already in accelerated compositing mode, but the root compositing layer changed. + + m_exitCompositingTimer.stop(); + m_wantsToExitAcceleratedCompositingMode = false; + + // If we haven't sent the EnterAcceleratedCompositingMode message, make sure that the + // layer tree host calls us back after the next layer flush so we can send it then. + if (!m_compositingAccordingToProxyMessages) + m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(true); + + m_layerTreeHost->setRootCompositingLayer(graphicsLayer); + } + } else { + if (m_layerTreeHost) { + m_layerTreeHost->setRootCompositingLayer(0); + if (!m_alwaysUseCompositing) { + // We'll exit accelerated compositing mode on a timer, to avoid re-entering + // compositing code via display() and layout. + // If we're leaving compositing mode because of a setSize, it is safe to + // exit accelerated compositing mode right away. + if (m_inUpdateBackingStoreState) + exitAcceleratedCompositingMode(); + else + exitAcceleratedCompositingModeSoon(); + } + } + } +} + +void DrawingAreaImpl::scheduleCompositingLayerSync() +{ + if (!m_layerTreeHost) + return; + m_layerTreeHost->scheduleLayerFlush(); +} + +void DrawingAreaImpl::updateBackingStoreState(uint64_t stateID, bool respondImmediately, float deviceScaleFactor, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset) +{ + ASSERT(!m_inUpdateBackingStoreState); + m_inUpdateBackingStoreState = true; + + ASSERT_ARG(stateID, stateID >= m_backingStoreStateID); + if (stateID != m_backingStoreStateID) { + m_backingStoreStateID = stateID; + m_shouldSendDidUpdateBackingStoreState = true; + + m_webPage->setDeviceScaleFactor(deviceScaleFactor); + m_webPage->setSize(size); + m_webPage->layoutIfNeeded(); + m_webPage->scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset); + + if (m_layerTreeHost) { + m_layerTreeHost->deviceScaleFactorDidChange(); + m_layerTreeHost->sizeDidChange(size); + } else + m_dirtyRegion = m_webPage->bounds(); + } else { + ASSERT(size == m_webPage->size()); + if (!m_shouldSendDidUpdateBackingStoreState) { + // We've already sent a DidUpdateBackingStoreState message for this state. We have nothing more to do. + m_inUpdateBackingStoreState = false; + return; + } + } + + // The UI process has updated to a new backing store state. Any Update messages we sent before + // this point will be ignored. We wait to set this to false until after updating the page's + // size so that any displays triggered by the relayout will be ignored. If we're supposed to + // respond to the UpdateBackingStoreState message immediately, we'll do a display anyway in + // sendDidUpdateBackingStoreState; otherwise we shouldn't do one right now. + m_isWaitingForDidUpdate = false; + + if (respondImmediately) { + // Make sure to resume painting if we're supposed to respond immediately, otherwise we'll just + // send back an empty UpdateInfo struct. + if (m_isPaintingSuspended) + resumePainting(); + + sendDidUpdateBackingStoreState(); + } + + m_inUpdateBackingStoreState = false; +} + +void DrawingAreaImpl::sendDidUpdateBackingStoreState() +{ + ASSERT(!m_isWaitingForDidUpdate); + ASSERT(m_shouldSendDidUpdateBackingStoreState); + + m_shouldSendDidUpdateBackingStoreState = false; + + UpdateInfo updateInfo; + + if (!m_isPaintingSuspended && !m_layerTreeHost) + display(updateInfo); + + LayerTreeContext layerTreeContext; + + if (m_isPaintingSuspended || m_layerTreeHost) { + updateInfo.viewSize = m_webPage->size(); + updateInfo.deviceScaleFactor = m_webPage->corePage()->deviceScaleFactor(); + + if (m_layerTreeHost) { + layerTreeContext = m_layerTreeHost->layerTreeContext(); + + // We don't want the layer tree host to notify after the next scheduled + // layer flush because that might end up sending an EnterAcceleratedCompositingMode + // message back to the UI process, but the updated layer tree context + // will be sent back in the DidUpdateBackingStoreState message. + m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false); + m_layerTreeHost->forceRepaint(); + } + } + + m_webPage->send(Messages::DrawingAreaProxy::DidUpdateBackingStoreState(m_backingStoreStateID, updateInfo, layerTreeContext)); + m_compositingAccordingToProxyMessages = !layerTreeContext.isEmpty(); +} + +void DrawingAreaImpl::didUpdate() +{ + // We might get didUpdate messages from the UI process even after we've + // entered accelerated compositing mode. Ignore them. + if (m_layerTreeHost) + return; + + m_isWaitingForDidUpdate = false; + + // Display if needed. We call displayTimerFired here since it will throttle updates to 60fps. + displayTimerFired(); +} + +void DrawingAreaImpl::suspendPainting() +{ + ASSERT(!m_isPaintingSuspended); + + if (m_layerTreeHost) + m_layerTreeHost->pauseRendering(); + + m_isPaintingSuspended = true; + m_displayTimer.stop(); + + m_webPage->corePage()->suspendScriptedAnimations(); +} + +void DrawingAreaImpl::resumePainting() +{ + if (!m_isPaintingSuspended) { + // FIXME: We can get a call to resumePainting when painting is not suspended. + // This happens when sending a synchronous message to create a new page. See <rdar://problem/8976531>. + return; + } + + if (m_layerTreeHost) + m_layerTreeHost->resumeRendering(); + + m_isPaintingSuspended = false; + + // FIXME: We shouldn't always repaint everything here. + setNeedsDisplay(m_webPage->bounds()); + + m_webPage->corePage()->resumeScriptedAnimations(); +} + +void DrawingAreaImpl::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLayer) +{ + m_exitCompositingTimer.stop(); + m_wantsToExitAcceleratedCompositingMode = false; + + ASSERT(!m_layerTreeHost); + + m_layerTreeHost = LayerTreeHost::create(m_webPage); + if (!m_inUpdateBackingStoreState) + m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(true); + + m_layerTreeHost->setRootCompositingLayer(graphicsLayer); + + // Non-composited content will now be handled exclusively by the layer tree host. + m_dirtyRegion = Region(); + m_scrollRect = IntRect(); + m_scrollOffset = IntSize(); + m_displayTimer.stop(); + m_isWaitingForDidUpdate = false; +} + +void DrawingAreaImpl::exitAcceleratedCompositingMode() +{ + if (m_alwaysUseCompositing && !m_webPage->mainFrameHasCustomRepresentation()) + return; + + ASSERT(!m_layerTreeStateIsFrozen); + + m_exitCompositingTimer.stop(); + m_wantsToExitAcceleratedCompositingMode = false; + + ASSERT(m_layerTreeHost); + + m_layerTreeHost->invalidate(); + m_layerTreeHost = nullptr; + m_dirtyRegion = m_webPage->bounds(); + + if (m_inUpdateBackingStoreState) + return; + + if (m_shouldSendDidUpdateBackingStoreState) { + sendDidUpdateBackingStoreState(); + return; + } + + UpdateInfo updateInfo; + if (m_isPaintingSuspended) { + updateInfo.viewSize = m_webPage->size(); + updateInfo.deviceScaleFactor = m_webPage->corePage()->deviceScaleFactor(); + } else + display(updateInfo); + +#if USE(ACCELERATED_COMPOSITING) + // Send along a complete update of the page so we can paint the contents right after we exit the + // accelerated compositing mode, eliminiating flicker. + if (m_compositingAccordingToProxyMessages) { + m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(m_backingStoreStateID, updateInfo)); + m_compositingAccordingToProxyMessages = false; + } else { + // If we left accelerated compositing mode before we sent an EnterAcceleratedCompositingMode message to the + // UI process, we still need to let it know about the new contents, so send an Update message. + m_webPage->send(Messages::DrawingAreaProxy::Update(m_backingStoreStateID, updateInfo)); + } +#endif +} + +void DrawingAreaImpl::exitAcceleratedCompositingModeSoon() +{ + if (m_layerTreeStateIsFrozen) { + m_wantsToExitAcceleratedCompositingMode = true; + return; + } + + if (exitAcceleratedCompositingModePending()) + return; + + m_exitCompositingTimer.startOneShot(0); +} + +void DrawingAreaImpl::scheduleDisplay() +{ + ASSERT(!m_layerTreeHost); + + if (m_isWaitingForDidUpdate) + return; + + if (m_isPaintingSuspended) + return; + + if (m_dirtyRegion.isEmpty()) + return; + + if (m_displayTimer.isActive()) + return; + + m_displayTimer.startOneShot(0); +} + +void DrawingAreaImpl::displayTimerFired() +{ + display(); +} + +void DrawingAreaImpl::display() +{ + ASSERT(!m_layerTreeHost); + ASSERT(!m_isWaitingForDidUpdate); + ASSERT(!m_inUpdateBackingStoreState); + + if (m_isPaintingSuspended) + return; + + if (m_dirtyRegion.isEmpty()) + return; + + if (m_shouldSendDidUpdateBackingStoreState) { + sendDidUpdateBackingStoreState(); + return; + } + + UpdateInfo updateInfo; + display(updateInfo); + + if (m_layerTreeHost) { + // The call to update caused layout which turned on accelerated compositing. + // Don't send an Update message in this case. + return; + } + + m_webPage->send(Messages::DrawingAreaProxy::Update(m_backingStoreStateID, updateInfo)); + m_isWaitingForDidUpdate = true; +} + +static bool shouldPaintBoundsRect(const IntRect& bounds, const Vector<IntRect>& rects) +{ + const size_t rectThreshold = 10; + const double wastedSpaceThreshold = 0.75; + + if (rects.size() <= 1 || rects.size() > rectThreshold) + return true; + + // Attempt to guess whether or not we should use the region bounds rect or the individual rects. + // We do this by computing the percentage of "wasted space" in the bounds. If that wasted space + // is too large, then we will do individual rect painting instead. + unsigned boundsArea = bounds.width() * bounds.height(); + unsigned rectsArea = 0; + for (size_t i = 0; i < rects.size(); ++i) + rectsArea += rects[i].width() * rects[i].height(); + + double wastedSpace = 1 - (static_cast<double>(rectsArea) / boundsArea); + + return wastedSpace <= wastedSpaceThreshold; +} + +#if !PLATFORM(WIN) +PassOwnPtr<GraphicsContext> DrawingAreaImpl::createGraphicsContext(ShareableBitmap* bitmap) +{ + return bitmap->createGraphicsContext(); +} +#endif + +void DrawingAreaImpl::display(UpdateInfo& updateInfo) +{ + ASSERT(!m_isPaintingSuspended); + ASSERT(!m_layerTreeHost); + ASSERT(!m_webPage->size().isEmpty()); + + // FIXME: It would be better if we could avoid painting altogether when there is a custom representation. + if (m_webPage->mainFrameHasCustomRepresentation()) { + // ASSUMPTION: the custom representation will be painting the dirty region for us. + m_dirtyRegion = Region(); + return; + } + + m_webPage->layoutIfNeeded(); + + // The layout may have put the page into accelerated compositing mode. If the LayerTreeHost is + // in charge of displaying, we have nothing more to do. + if (m_layerTreeHost) + return; + + updateInfo.viewSize = m_webPage->size(); + updateInfo.deviceScaleFactor = m_webPage->corePage()->deviceScaleFactor(); + + IntRect bounds = m_dirtyRegion.bounds(); + ASSERT(m_webPage->bounds().contains(bounds)); + + IntSize bitmapSize = bounds.size(); + float deviceScaleFactor = m_webPage->corePage()->deviceScaleFactor(); + bitmapSize.scale(deviceScaleFactor); + RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(bitmapSize, ShareableBitmap::SupportsAlpha); + if (!bitmap) + return; + + if (!bitmap->createHandle(updateInfo.bitmapHandle)) + return; + + Vector<IntRect> rects = m_dirtyRegion.rects(); + + if (shouldPaintBoundsRect(bounds, rects)) { + rects.clear(); + rects.append(bounds); + } + + updateInfo.scrollRect = m_scrollRect; + updateInfo.scrollOffset = m_scrollOffset; + + m_dirtyRegion = Region(); + m_scrollRect = IntRect(); + m_scrollOffset = IntSize(); + + OwnPtr<GraphicsContext> graphicsContext = createGraphicsContext(bitmap.get()); + graphicsContext->applyDeviceScaleFactor(deviceScaleFactor); + + updateInfo.updateRectBounds = bounds; + + graphicsContext->translate(-bounds.x(), -bounds.y()); + + for (size_t i = 0; i < rects.size(); ++i) { + m_webPage->drawRect(*graphicsContext, rects[i]); + if (m_webPage->hasPageOverlay()) + m_webPage->drawPageOverlay(*graphicsContext, rects[i]); + updateInfo.updateRects.append(rects[i]); + } + + // Layout can trigger more calls to setNeedsDisplay and we don't want to process them + // until the UI process has painted the update, so we stop the timer here. + m_displayTimer.stop(); +} + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +void DrawingAreaImpl::didReceiveLayerTreeHostMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) +{ + if (m_layerTreeHost) + m_layerTreeHost->didReceiveLayerTreeHostMessage(connection, messageID, arguments); +} +#endif + + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h new file mode 100644 index 000000000..0dabf603a --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef DrawingAreaImpl_h +#define DrawingAreaImpl_h + +#include "DrawingArea.h" +#include "LayerTreeHost.h" +#include "RunLoop.h" +#include <WebCore/Region.h> + +namespace WebCore { + class GraphicsContext; +} + +namespace WebKit { + +class ShareableBitmap; +class UpdateInfo; + +class DrawingAreaImpl : public DrawingArea { +public: + static PassOwnPtr<DrawingAreaImpl> create(WebPage*, const WebPageCreationParameters&); + virtual ~DrawingAreaImpl(); + + void layerHostDidFlushLayers(); + +private: + DrawingAreaImpl(WebPage*, const WebPageCreationParameters&); + + // DrawingArea + virtual void setNeedsDisplay(const WebCore::IntRect&); + virtual void scroll(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset); + virtual void setLayerTreeStateIsFrozen(bool); + virtual bool layerTreeStateIsFrozen() const { return m_layerTreeStateIsFrozen; } + virtual void forceRepaint(); + + virtual void didInstallPageOverlay(); + virtual void didUninstallPageOverlay(); + virtual void setPageOverlayNeedsDisplay(const WebCore::IntRect&); + + virtual void setPaintingEnabled(bool); + + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*); + virtual void scheduleCompositingLayerSync(); + +#if PLATFORM(WIN) + virtual void scheduleChildWindowGeometryUpdate(const WindowGeometry&); +#endif + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) + virtual void didReceiveLayerTreeHostMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); +#endif + + // CoreIPC message handlers. + virtual void updateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, float deviceScaleFactor, const WebCore::IntSize&, const WebCore::IntSize& scrollOffset); + virtual void didUpdate(); + virtual void suspendPainting(); + virtual void resumePainting(); + + virtual void pageCustomRepresentationChanged(); + + void sendDidUpdateBackingStoreState(); + + void enterAcceleratedCompositingMode(WebCore::GraphicsLayer*); + void exitAcceleratedCompositingModeSoon(); + bool exitAcceleratedCompositingModePending() const { return m_exitCompositingTimer.isActive(); } + void exitAcceleratedCompositingMode(); + + void scheduleDisplay(); + void displayTimerFired(); + void display(); + void display(UpdateInfo&); + PassOwnPtr<WebCore::GraphicsContext> createGraphicsContext(ShareableBitmap*); + + uint64_t m_backingStoreStateID; + + WebCore::Region m_dirtyRegion; + WebCore::IntRect m_scrollRect; + WebCore::IntSize m_scrollOffset; + + // Whether painting is enabled. If painting is disabled, any calls to setNeedsDisplay and scroll are ignored. + bool m_isPaintingEnabled; + + // Whether we're currently processing an UpdateBackingStoreState message. + bool m_inUpdateBackingStoreState; + + // When true, we should send an UpdateBackingStoreState message instead of any other messages + // we normally send to the UI process. + bool m_shouldSendDidUpdateBackingStoreState; + + // Whether we're waiting for a DidUpdate message. Used for throttling paints so that the + // web process won't paint more frequent than the UI process can handle. + bool m_isWaitingForDidUpdate; + + // True between sending the 'enter compositing' messages, and the 'exit compositing' message. + bool m_compositingAccordingToProxyMessages; + + // When true, we maintain the layer tree in its current state by not leaving accelerated compositing mode + // and not scheduling layer flushes. + bool m_layerTreeStateIsFrozen; + + // True when we were asked to exit accelerated compositing mode but couldn't because layer tree + // state was frozen. + bool m_wantsToExitAcceleratedCompositingMode; + + // Whether painting is suspended. We'll still keep track of the dirty region but we + // won't paint until painting has resumed again. + bool m_isPaintingSuspended; + bool m_alwaysUseCompositing; + + RunLoop::Timer<DrawingAreaImpl> m_displayTimer; + RunLoop::Timer<DrawingAreaImpl> m_exitCompositingTimer; + + // The layer tree host that handles accelerated compositing. + RefPtr<LayerTreeHost> m_layerTreeHost; +}; + +} // namespace WebKit + +#endif // DrawingAreaImpl_h diff --git a/Source/WebKit2/WebProcess/WebPage/EncoderAdapter.cpp b/Source/WebKit2/WebProcess/WebPage/EncoderAdapter.cpp new file mode 100644 index 000000000..547b68d73 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/EncoderAdapter.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "EncoderAdapter.h" + +#include "DataReference.h" +#include "WebCoreArgumentCoders.h" + +namespace WebKit { + +EncoderAdapter::EncoderAdapter() + : m_encoder(CoreIPC::ArgumentEncoder::create(0)) +{ +} + +CoreIPC::DataReference EncoderAdapter::dataReference() const +{ + return CoreIPC::DataReference(m_encoder->buffer(), m_encoder->bufferSize()); +} + +void EncoderAdapter::encodeBytes(const uint8_t* bytes, size_t size) +{ + m_encoder->encodeVariableLengthByteArray(CoreIPC::DataReference(bytes, size)); +} + +void EncoderAdapter::encodeBool(bool value) +{ + m_encoder->encodeBool(value); +} + +void EncoderAdapter::encodeUInt32(uint32_t value) +{ + m_encoder->encodeUInt32(value); +} + +void EncoderAdapter::encodeUInt64(uint64_t value) +{ + m_encoder->encodeUInt64(value); +} + +void EncoderAdapter::encodeInt32(int32_t value) +{ + m_encoder->encodeInt32(value); +} + +void EncoderAdapter::encodeInt64(int64_t value) +{ + m_encoder->encodeInt64(value); +} + +void EncoderAdapter::encodeFloat(float value) +{ + m_encoder->encodeFloat(value); +} + +void EncoderAdapter::encodeDouble(double value) +{ + m_encoder->encodeDouble(value); +} + +void EncoderAdapter::encodeString(const String& value) +{ + m_encoder->encode(value); +} + +} diff --git a/Source/WebKit2/WebProcess/WebPage/EncoderAdapter.h b/Source/WebKit2/WebProcess/WebPage/EncoderAdapter.h new file mode 100644 index 000000000..47de7afd5 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/EncoderAdapter.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef EncoderAdapter_h +#define EncoderAdapter_h + +#include <wtf/Encoder.h> +#include <wtf/Forward.h> +#include <wtf/OwnPtr.h> + +namespace CoreIPC { + class ArgumentEncoder; + class DataReference; +} + +namespace WebKit { + +class EncoderAdapter : public Encoder { +public: + EncoderAdapter(); + + CoreIPC::DataReference dataReference() const; + +private: + virtual void encodeBytes(const uint8_t*, size_t); + virtual void encodeBool(bool); + virtual void encodeUInt32(uint32_t); + virtual void encodeUInt64(uint64_t); + virtual void encodeInt32(int32_t); + virtual void encodeInt64(int64_t); + virtual void encodeFloat(float); + virtual void encodeDouble(double); + virtual void encodeString(const String&); + + OwnPtr<CoreIPC::ArgumentEncoder> m_encoder; +}; + +} // namespace WebKit + +#endif // EncoderAdapter_h diff --git a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp new file mode 100644 index 000000000..6486587d0 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.cpp @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "EventDispatcher.h" + +#include "RunLoop.h" +#include "WebEvent.h" +#include "WebEventConversion.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include "WebProcess.h" +#include <WebCore/Page.h> +#include <wtf/MainThread.h> + +#if ENABLE(THREADED_SCROLLING) +#include <WebCore/ScrollingCoordinator.h> +#endif + +using namespace WebCore; + +namespace WebKit { + +EventDispatcher::EventDispatcher() +{ +} + +EventDispatcher::~EventDispatcher() +{ +} + +#if ENABLE(THREADED_SCROLLING) +void EventDispatcher::addScrollingCoordinatorForPage(WebPage* webPage) +{ + MutexLocker locker(m_scrollingCoordinatorsMutex); + + ASSERT(webPage->corePage()->scrollingCoordinator()); + ASSERT(!m_scrollingCoordinators.contains(webPage->pageID())); + m_scrollingCoordinators.set(webPage->pageID(), webPage->corePage()->scrollingCoordinator()); +} + +void EventDispatcher::removeScrollingCoordinatorForPage(WebPage* webPage) +{ + MutexLocker locker(m_scrollingCoordinatorsMutex); + ASSERT(m_scrollingCoordinators.contains(webPage->pageID())); + + m_scrollingCoordinators.remove(webPage->pageID()); +} +#endif + +void EventDispatcher::didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, bool& didHandleMessage) +{ + if (messageID.is<CoreIPC::MessageClassEventDispatcher>()) { + didReceiveEventDispatcherMessageOnConnectionWorkQueue(connection, messageID, arguments, didHandleMessage); + return; + } +} + +void EventDispatcher::wheelEvent(uint64_t pageID, const WebWheelEvent& wheelEvent) +{ +#if ENABLE(THREADED_SCROLLING) + MutexLocker locker(m_scrollingCoordinatorsMutex); + if (ScrollingCoordinator* scrollingCoordinator = m_scrollingCoordinators.get(pageID).get()) { + PlatformWheelEvent platformWheelEvent = platform(wheelEvent); + + if (scrollingCoordinator->handleWheelEvent(platformWheelEvent)) { + sendDidHandleEvent(pageID, wheelEvent); + return; + } + } +#endif + + RunLoop::main()->dispatch(bind(&EventDispatcher::dispatchWheelEvent, this, pageID, wheelEvent)); +} + +#if ENABLE(GESTURE_EVENTS) +void EventDispatcher::gestureEvent(uint64_t pageID, const WebGestureEvent& gestureEvent) +{ +#if ENABLE(THREADED_SCROLLING) + MutexLocker locker(m_scrollingCoordinatorsMutex); + if (ScrollingCoordinator* scrollingCoordinator = m_scrollingCoordinators.get(pageID).get()) { + PlatformGestureEvent platformGestureEvent = platform(gestureEvent); + + if (scrollingCoordinator->handleGestureEvent(platformGestureEvent)) { + sendDidHandleEvent(pageID, gestureEvent); + return; + } + } +#endif + + RunLoop::main()->dispatch(bind(&EventDispatcher::dispatchGestureEvent, this, pageID, gestureEvent)); +} +#endif + +void EventDispatcher::dispatchWheelEvent(uint64_t pageID, const WebWheelEvent& wheelEvent) +{ + ASSERT(isMainThread()); + + WebPage* webPage = WebProcess::shared().webPage(pageID); + if (!webPage) + return; + + webPage->wheelEvent(wheelEvent); +} + +#if ENABLE(GESTURE_EVENTS) +void EventDispatcher::dispatchGestureEvent(uint64_t pageID, const WebGestureEvent& gestureEvent) +{ + ASSERT(isMainThread()); + + WebPage* webPage = WebProcess::shared().webPage(pageID); + if (!webPage) + return; + + webPage->gestureEvent(gestureEvent); +} +#endif + +#if ENABLE(THREADED_SCROLLING) +void EventDispatcher::sendDidHandleEvent(uint64_t pageID, const WebEvent& event) +{ + WebProcess::shared().connection()->send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(event.type()), true), pageID); +} +#endif + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h new file mode 100644 index 000000000..7cd2f9550 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef EventDispatcher_h +#define EventDispatcher_h + +#include "Connection.h" +#include <wtf/HashMap.h> +#include <wtf/Noncopyable.h> +#include <wtf/RefPtr.h> +#include <wtf/ThreadingPrimitives.h> + +namespace WebCore { + class ScrollingCoordinator; +} + +namespace WebKit { + +class WebEvent; +class WebPage; +class WebWheelEvent; + +#if ENABLE(GESTURE_EVENTS) +class WebGestureEvent; +#endif + +class EventDispatcher : public CoreIPC::Connection::QueueClient { + WTF_MAKE_NONCOPYABLE(EventDispatcher); + +public: + EventDispatcher(); + ~EventDispatcher(); + +#if ENABLE(THREADED_SCROLLING) + void addScrollingCoordinatorForPage(WebPage*); + void removeScrollingCoordinatorForPage(WebPage*); +#endif + +private: + // CoreIPC::Connection::QueueClient + virtual void didReceiveMessageOnConnectionWorkQueue(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, bool& didHandleMessage) OVERRIDE; + + // Implemented in generated EventDispatcherMessageReceiver.cpp + void didReceiveEventDispatcherMessageOnConnectionWorkQueue(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder* arguments, bool& didHandleMessage); + + // Message handlers + void wheelEvent(uint64_t pageID, const WebWheelEvent&); +#if ENABLE(GESTURE_EVENTS) + void gestureEvent(uint64_t pageID, const WebGestureEvent&); +#endif + + // This is called on the main thread. + void dispatchWheelEvent(uint64_t pageID, const WebWheelEvent&); +#if ENABLE(GESTURE_EVENTS) + void dispatchGestureEvent(uint64_t pageID, const WebGestureEvent&); +#endif + +#if ENABLE(THREADED_SCROLLING) + void sendDidHandleEvent(uint64_t pageID, const WebEvent&); + + Mutex m_scrollingCoordinatorsMutex; + HashMap<uint64_t, RefPtr<WebCore::ScrollingCoordinator> > m_scrollingCoordinators; +#endif +}; + +} // namespace WebKit + +#endif // EventDispatcher_h diff --git a/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in new file mode 100644 index 000000000..a15571be5 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/EventDispatcher.messages.in @@ -0,0 +1,30 @@ +# Copyright (C) 2011 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. + +messages -> EventDispatcher { + WheelEvent(uint64_t pageID, WebKit::WebWheelEvent event) DispatchOnConnectionQueue + +#if ENABLE(GESTURE_EVENTS) + GestureEvent(uint64_t pageID, WebKit::WebGestureEvent event) DispatchOnConnectionQueue +#endif + +} diff --git a/Source/WebKit2/WebProcess/WebPage/FindController.cpp b/Source/WebKit2/WebProcess/WebPage/FindController.cpp new file mode 100644 index 000000000..9bdd80bb9 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/FindController.cpp @@ -0,0 +1,360 @@ +/* + * 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 "config.h" +#include "FindController.h" + +#include "ShareableBitmap.h" +#include "WKPage.h" +#include "WebCoreArgumentCoders.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include "WebProcess.h" +#include <WebCore/DocumentMarkerController.h> +#include <WebCore/FocusController.h> +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/GraphicsContext.h> +#include <WebCore/Page.h> + +using namespace std; +using namespace WebCore; + +namespace WebKit { + +static WebCore::FindOptions core(FindOptions options) +{ + return (options & FindOptionsCaseInsensitive ? CaseInsensitive : 0) + | (options & FindOptionsAtWordStarts ? AtWordStarts : 0) + | (options & FindOptionsTreatMedialCapitalAsWordStart ? TreatMedialCapitalAsWordStart : 0) + | (options & FindOptionsBackwards ? Backwards : 0) + | (options & FindOptionsWrapAround ? WrapAround : 0); +} + +FindController::FindController(WebPage* webPage) + : m_webPage(webPage) + , m_findPageOverlay(0) + , m_isShowingFindIndicator(false) +{ +} + +FindController::~FindController() +{ +} + +void FindController::countStringMatches(const String& string, FindOptions options, unsigned maxMatchCount) +{ + if (maxMatchCount == numeric_limits<unsigned>::max()) + --maxMatchCount; + + unsigned matchCount = m_webPage->corePage()->markAllMatchesForText(string, core(options), false, maxMatchCount + 1); + m_webPage->corePage()->unmarkAllTextMatches(); + + // Check if we have more matches than allowed. + if (matchCount > maxMatchCount) + matchCount = static_cast<unsigned>(kWKMoreThanMaximumMatchCount); + + m_webPage->send(Messages::WebPageProxy::DidCountStringMatches(string, matchCount)); +} + +static Frame* frameWithSelection(Page* page) +{ + for (Frame* frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + if (frame->selection()->isRange()) + return frame; + } + + return 0; +} + +void FindController::findString(const String& string, FindOptions options, unsigned maxMatchCount) +{ + m_webPage->corePage()->unmarkAllTextMatches(); + + bool found = m_webPage->corePage()->findString(string, core(options)); + + Frame* selectedFrame = frameWithSelection(m_webPage->corePage()); + + bool shouldShowOverlay = false; + + if (!found) { + // Clear the selection. + if (selectedFrame) + selectedFrame->selection()->clear(); + + hideFindIndicator(); + + m_webPage->send(Messages::WebPageProxy::DidFailToFindString(string)); + } else { + shouldShowOverlay = options & FindOptionsShowOverlay; + + if (shouldShowOverlay) { + if (maxMatchCount == numeric_limits<unsigned>::max()) + --maxMatchCount; + + unsigned matchCount = m_webPage->corePage()->markAllMatchesForText(string, core(options), false, maxMatchCount + 1); + + // Check if we have more matches than allowed. + if (matchCount > maxMatchCount) { + shouldShowOverlay = false; + matchCount = static_cast<unsigned>(kWKMoreThanMaximumMatchCount); + } + + m_webPage->send(Messages::WebPageProxy::DidFindString(string, matchCount)); + } + + if (!(options & FindOptionsShowFindIndicator) || !updateFindIndicator(selectedFrame, shouldShowOverlay)) { + // Either we shouldn't show the find indicator, or we couldn't update it. + hideFindIndicator(); + } + } + + if (!shouldShowOverlay) { + if (m_findPageOverlay) { + // Get rid of the overlay. + m_webPage->uninstallPageOverlay(m_findPageOverlay, false); + } + + ASSERT(!m_findPageOverlay); + return; + } + + if (!m_findPageOverlay) { + RefPtr<PageOverlay> findPageOverlay = PageOverlay::create(this); + m_findPageOverlay = findPageOverlay.get(); + m_webPage->installPageOverlay(findPageOverlay.release()); + } else { + // The page overlay needs to be repainted. + m_findPageOverlay->setNeedsDisplay(); + } +} + +void FindController::hideFindUI() +{ + if (m_findPageOverlay) + m_webPage->uninstallPageOverlay(m_findPageOverlay, false); + + hideFindIndicator(); +} + +bool FindController::updateFindIndicator(Frame* selectedFrame, bool isShowingOverlay, bool shouldAnimate) +{ + if (!selectedFrame) + return false; + + IntRect selectionRect = enclosingIntRect(selectedFrame->selection()->bounds()); + + // Selection rect can be empty for matches that are currently obscured from view. + if (selectionRect.isEmpty()) + return false; + + // We want the selection rect in window coordinates. + IntRect selectionRectInWindowCoordinates = selectedFrame->view()->contentsToWindow(selectionRect); + + Vector<FloatRect> textRects; + selectedFrame->selection()->getClippedVisibleTextRectangles(textRects); + + IntSize backingStoreSize = selectionRect.size(); + backingStoreSize.scale(m_webPage->corePage()->deviceScaleFactor()); + + // Create a backing store and paint the find indicator text into it. + RefPtr<ShareableBitmap> findIndicatorTextBackingStore = ShareableBitmap::createShareable(backingStoreSize, ShareableBitmap::SupportsAlpha); + if (!findIndicatorTextBackingStore) + return false; + + OwnPtr<GraphicsContext> graphicsContext = findIndicatorTextBackingStore->createGraphicsContext(); + graphicsContext->scale(FloatSize(m_webPage->corePage()->deviceScaleFactor(), m_webPage->corePage()->deviceScaleFactor())); + + IntRect paintRect = selectionRect; + paintRect.move(selectedFrame->view()->frameRect().x(), selectedFrame->view()->frameRect().y()); + paintRect.move(-selectedFrame->view()->scrollOffset()); + + graphicsContext->translate(-paintRect.x(), -paintRect.y()); + selectedFrame->view()->setPaintBehavior(PaintBehaviorSelectionOnly | PaintBehaviorForceBlackText | PaintBehaviorFlattenCompositingLayers); + selectedFrame->document()->updateLayout(); + + selectedFrame->view()->paint(graphicsContext.get(), paintRect); + selectedFrame->view()->setPaintBehavior(PaintBehaviorNormal); + + ShareableBitmap::Handle handle; + if (!findIndicatorTextBackingStore->createHandle(handle)) + return false; + + // We want the text rects in selection rect coordinates. + Vector<FloatRect> textRectsInSelectionRectCoordinates; + + for (size_t i = 0; i < textRects.size(); ++i) { + IntRect textRectInSelectionRectCoordinates = selectedFrame->view()->contentsToWindow(enclosingIntRect(textRects[i])); + textRectInSelectionRectCoordinates.move(-selectionRectInWindowCoordinates.x(), -selectionRectInWindowCoordinates.y()); + + textRectsInSelectionRectCoordinates.append(textRectInSelectionRectCoordinates); + } + + m_webPage->send(Messages::WebPageProxy::SetFindIndicator(selectionRectInWindowCoordinates, textRectsInSelectionRectCoordinates, m_webPage->corePage()->deviceScaleFactor(), handle, !isShowingOverlay, shouldAnimate)); + m_isShowingFindIndicator = true; + + return true; +} + +void FindController::hideFindIndicator() +{ + if (!m_isShowingFindIndicator) + return; + + ShareableBitmap::Handle handle; + m_webPage->send(Messages::WebPageProxy::SetFindIndicator(FloatRect(), Vector<FloatRect>(), m_webPage->corePage()->deviceScaleFactor(), handle, false, true)); + m_isShowingFindIndicator = false; +} + +void FindController::showFindIndicatorInSelection() +{ + Frame* selectedFrame = m_webPage->corePage()->focusController()->focusedOrMainFrame(); + if (!selectedFrame) + return; + + updateFindIndicator(selectedFrame, false); +} + +void FindController::deviceScaleFactorDidChange() +{ + ASSERT(isShowingOverlay()); + + Frame* selectedFrame = frameWithSelection(m_webPage->corePage()); + if (!selectedFrame) + return; + + updateFindIndicator(selectedFrame, true, false); +} + +Vector<IntRect> FindController::rectsForTextMatches() +{ + Vector<IntRect> rects; + + for (Frame* frame = m_webPage->corePage()->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + Document* document = frame->document(); + if (!document) + continue; + + IntRect visibleRect = frame->view()->visibleContentRect(); + Vector<IntRect> frameRects = document->markers()->renderedRectsForMarkers(DocumentMarker::TextMatch); + IntPoint frameOffset(-frame->view()->scrollOffset().width(), -frame->view()->scrollOffset().height()); + frameOffset = frame->view()->convertToContainingWindow(frameOffset); + + for (Vector<IntRect>::iterator it = frameRects.begin(), end = frameRects.end(); it != end; ++it) { + it->intersect(visibleRect); + it->move(frameOffset.x(), frameOffset.y()); + rects.append(*it); + } + } + + return rects; +} + +void FindController::pageOverlayDestroyed(PageOverlay*) +{ +} + +void FindController::willMoveToWebPage(PageOverlay*, WebPage* webPage) +{ + if (webPage) + return; + + // The page overlay is moving away from the web page, reset it. + ASSERT(m_findPageOverlay); + m_findPageOverlay = 0; +} + +void FindController::didMoveToWebPage(PageOverlay*, WebPage*) +{ +} + +static const float shadowOffsetX = 0.0; +static const float shadowOffsetY = 1.0; +static const float shadowBlurRadius = 2.0; +static const float whiteFrameThickness = 1.0; + +static const float overlayBackgroundRed = 0.1; +static const float overlayBackgroundGreen = 0.1; +static const float overlayBackgroundBlue = 0.1; +static const float overlayBackgroundAlpha = 0.25; + +static Color overlayBackgroundColor(float fractionFadedIn) +{ + return Color(overlayBackgroundRed, overlayBackgroundGreen, overlayBackgroundBlue, overlayBackgroundAlpha * fractionFadedIn); +} + +static Color holeShadowColor(float fractionFadedIn) +{ + return Color(0.0f, 0.0f, 0.0f, fractionFadedIn); +} + +static Color holeFillColor(float fractionFadedIn) +{ + return Color(1.0f, 1.0f, 1.0f, fractionFadedIn); +} + +void FindController::drawRect(PageOverlay* pageOverlay, GraphicsContext& graphicsContext, const IntRect& dirtyRect) +{ + float fractionFadedIn = pageOverlay->fractionFadedIn(); + + Vector<IntRect> rects = rectsForTextMatches(); + + // Draw the background. + graphicsContext.fillRect(dirtyRect, overlayBackgroundColor(fractionFadedIn), ColorSpaceSRGB); + + { + GraphicsContextStateSaver stateSaver(graphicsContext); + + graphicsContext.setShadow(FloatSize(shadowOffsetX, shadowOffsetY), shadowBlurRadius, holeShadowColor(fractionFadedIn), ColorSpaceSRGB); + graphicsContext.setFillColor(holeFillColor(fractionFadedIn), ColorSpaceSRGB); + + // Draw white frames around the holes. + for (size_t i = 0; i < rects.size(); ++i) { + IntRect whiteFrameRect = rects[i]; + whiteFrameRect.inflate(1); + + graphicsContext.fillRect(whiteFrameRect); + } + } + + graphicsContext.setFillColor(Color::transparent, ColorSpaceSRGB); + + // Clear out the holes. + for (size_t i = 0; i < rects.size(); ++i) + graphicsContext.fillRect(rects[i]); +} + +bool FindController::mouseEvent(PageOverlay* pageOverlay, const WebMouseEvent& mouseEvent) +{ + // If we get a mouse down event inside the page overlay we should hide the find UI. + if (mouseEvent.type() == WebEvent::MouseDown) { + // Dismiss the overlay. + hideFindUI(); + } + + return false; +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/FindController.h b/Source/WebKit2/WebProcess/WebPage/FindController.h new file mode 100644 index 000000000..da03b79a7 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/FindController.h @@ -0,0 +1,84 @@ +/* + * 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. + */ + +#ifndef FindController_h +#define FindController_h + +#include "PageOverlay.h" +#include "WebFindOptions.h" +#include <wtf/Forward.h> +#include <wtf/Noncopyable.h> +#include <wtf/Vector.h> + +namespace WebCore { + class Frame; + class IntRect; +} + +namespace WebKit { + +class WebPage; + +class FindController : private PageOverlay::Client { + WTF_MAKE_NONCOPYABLE(FindController); + +public: + explicit FindController(WebPage*); + virtual ~FindController(); + + void findString(const String&, FindOptions, unsigned maxMatchCount); + void hideFindUI(); + void countStringMatches(const String&, FindOptions, unsigned maxMatchCount); + + void hideFindIndicator(); + void showFindIndicatorInSelection(); + + bool isShowingOverlay() const { return m_isShowingFindIndicator && m_findPageOverlay; } + + void deviceScaleFactorDidChange(); + +private: + // PageOverlay::Client. + virtual void pageOverlayDestroyed(PageOverlay*); + virtual void willMoveToWebPage(PageOverlay*, WebPage*); + virtual void didMoveToWebPage(PageOverlay*, WebPage*); + virtual bool mouseEvent(PageOverlay*, const WebMouseEvent&); + virtual void drawRect(PageOverlay*, WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect); + + Vector<WebCore::IntRect> rectsForTextMatches(); + bool updateFindIndicator(WebCore::Frame* selectedFrame, bool isShowingOverlay, bool shouldAnimate = true); + +private: + WebPage* m_webPage; + PageOverlay* m_findPageOverlay; + + // Whether the UI process is showing the find indicator. Note that this can be true even if + // the find indicator isn't showing, but it will never be false when it is showing. + bool m_isShowingFindIndicator; +}; + +} // namespace WebKit + +#endif // FindController_h diff --git a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp new file mode 100644 index 000000000..031c3fa6a --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "LayerTreeHost.h" + +#if USE(CA) +#if PLATFORM(MAC) +#include "LayerTreeHostCAMac.h" +#elif PLATFORM(WIN) +#include "LayerTreeHostCAWin.h" +#endif +#endif + +#if PLATFORM(QT) && USE(TEXTURE_MAPPER) +#include "qt/LayerTreeHostQt.h" +#endif + +using namespace WebCore; + +namespace WebKit { + +PassRefPtr<LayerTreeHost> LayerTreeHost::create(WebPage* webPage) +{ +#if PLATFORM(MAC) + return LayerTreeHostCAMac::create(webPage); +#elif PLATFORM(WIN) && HAVE(WKQCA) + return LayerTreeHostCAWin::create(webPage); +#elif PLATFORM(QT) && USE(TEXTURE_MAPPER) + return LayerTreeHostQt::create(webPage); +#else + return 0; +#endif +} + +LayerTreeHost::LayerTreeHost(WebPage* webPage) + : m_webPage(webPage) +{ +} + +LayerTreeHost::~LayerTreeHost() +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h new file mode 100644 index 000000000..61fbe2fc3 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef LayerTreeHost_h +#define LayerTreeHost_h + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace CoreIPC { +class ArgumentDecoder; +class Connection; +class MessageID; +} + +namespace WebCore { +class FloatPoint; +class IntRect; +class IntSize; +class GraphicsLayer; +} + +namespace WebKit { + +class LayerTreeContext; +class UpdateInfo; +class WebPage; + +#if PLATFORM(WIN) +struct WindowGeometry; +#endif + +class LayerTreeHost : public RefCounted<LayerTreeHost> { +public: + static PassRefPtr<LayerTreeHost> create(WebPage*); + virtual ~LayerTreeHost(); + + static bool supportsAcceleratedCompositing(); + + virtual const LayerTreeContext& layerTreeContext() = 0; + virtual void scheduleLayerFlush() = 0; + virtual void setLayerFlushSchedulingEnabled(bool) = 0; + virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool) = 0; + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) = 0; + virtual void invalidate() = 0; + + virtual void setNonCompositedContentsNeedDisplay(const WebCore::IntRect&) = 0; + virtual void scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) = 0; + virtual void forceRepaint() = 0; + virtual void sizeDidChange(const WebCore::IntSize& newSize) = 0; + virtual void deviceScaleFactorDidChange() = 0; + + virtual void didInstallPageOverlay() = 0; + virtual void didUninstallPageOverlay() = 0; + virtual void setPageOverlayNeedsDisplay(const WebCore::IntRect&) = 0; + + virtual void pauseRendering() { } + virtual void resumeRendering() { } + +#if USE(TILED_BACKING_STORE) + virtual void setVisibleContentRectAndScale(const WebCore::IntRect&, float scale) { } + virtual void setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint&) { } + virtual void setVisibleContentRectForLayer(int layerID, const WebCore::IntRect&) { } + virtual void renderNextFrame() { } + virtual void purgeBackingStores() { } + virtual void didReceiveLayerTreeHostMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); +#endif + +#if PLATFORM(WIN) + virtual void scheduleChildWindowGeometryUpdate(const WindowGeometry&) = 0; +#endif + +protected: + explicit LayerTreeHost(WebPage*); + + WebPage* m_webPage; + + +#if USE(TILED_BACKING_STORE) + bool m_waitingForUIProcess; +#endif +}; + +#if !PLATFORM(WIN) && !PLATFORM(QT) +inline bool LayerTreeHost::supportsAcceleratedCompositing() +{ + return true; +} +#endif + +} // namespace WebKit + +#endif // LayerTreeHost_h diff --git a/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.messages.in b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.messages.in new file mode 100644 index 000000000..d2e9c384e --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/LayerTreeHost.messages.in @@ -0,0 +1,29 @@ +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. +# +# You should have received a copy of the GNU Library General Public License +# along with this library; see the file COPYING.LIB. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. +# + + +#if USE(TILED_BACKING_STORE) +messages -> LayerTreeHost { + SetVisibleContentRectForLayer(int layerID, WebCore::IntRect visibleContentRect) + SetVisibleContentRectTrajectoryVector(WebCore::FloatPoint trajectoryVectory) + SetVisibleContentRectAndScale(WebCore::IntRect contentRect, float scale) + RenderNextFrame() + PurgeBackingStores() +} +#endif diff --git a/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp b/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp new file mode 100644 index 000000000..aa32b6a09 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/PageOverlay.cpp @@ -0,0 +1,175 @@ +/* + * 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 "config.h" +#include "PageOverlay.h" + +#include "WebPage.h" +#include "WebProcess.h" +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/GraphicsContext.h> +#include <WebCore/Page.h> +#include <WebCore/ScrollbarTheme.h> + +using namespace WebCore; + +namespace WebKit { + +static const double fadeAnimationDuration = 0.2; +static const double fadeAnimationFrameRate = 30; + +PassRefPtr<PageOverlay> PageOverlay::create(Client* client) +{ + return adoptRef(new PageOverlay(client)); +} + +PageOverlay::PageOverlay(Client* client) + : m_client(client) + , m_webPage(0) + , m_fadeAnimationTimer(WebProcess::shared().runLoop(), this, &PageOverlay::fadeAnimationTimerFired) + , m_fadeAnimationStartTime(0.0) + , m_fadeAnimationDuration(fadeAnimationDuration) + , m_fadeAnimationType(NoAnimation) + , m_fractionFadedIn(1.0) +{ +} + +PageOverlay::~PageOverlay() +{ +} + +IntRect PageOverlay::bounds() const +{ + FrameView* frameView = m_webPage->corePage()->mainFrame()->view(); + + int width = frameView->width(); + int height = frameView->height(); + + if (!ScrollbarTheme::theme()->usesOverlayScrollbars()) { + if (frameView->verticalScrollbar()) + width -= frameView->verticalScrollbar()->width(); + if (frameView->horizontalScrollbar()) + height -= frameView->horizontalScrollbar()->height(); + } + return IntRect(0, 0, width, height); +} + +void PageOverlay::setPage(WebPage* webPage) +{ + m_client->willMoveToWebPage(this, webPage); + m_webPage = webPage; + m_client->didMoveToWebPage(this, webPage); + + m_fadeAnimationTimer.stop(); +} + +void PageOverlay::setNeedsDisplay(const IntRect& dirtyRect) +{ + if (m_webPage) + m_webPage->drawingArea()->setPageOverlayNeedsDisplay(dirtyRect); +} + +void PageOverlay::setNeedsDisplay() +{ + setNeedsDisplay(bounds()); +} + +void PageOverlay::drawRect(GraphicsContext& graphicsContext, const IntRect& dirtyRect) +{ + // If the dirty rect is outside the bounds, ignore it. + IntRect paintRect = intersection(dirtyRect, bounds()); + if (paintRect.isEmpty()) + return; + + GraphicsContextStateSaver stateSaver(graphicsContext); + graphicsContext.beginTransparencyLayer(1); + graphicsContext.setCompositeOperation(CompositeCopy); + + m_client->drawRect(this, graphicsContext, paintRect); + + graphicsContext.endTransparencyLayer(); +} + +bool PageOverlay::mouseEvent(const WebMouseEvent& mouseEvent) +{ + // Ignore events outside the bounds. + if (!bounds().contains(mouseEvent.position())) + return false; + + return m_client->mouseEvent(this, mouseEvent); +} + +void PageOverlay::startFadeInAnimation() +{ + m_fractionFadedIn = 0.0; + m_fadeAnimationType = FadeInAnimation; + + startFadeAnimation(); +} + +void PageOverlay::startFadeOutAnimation() +{ + m_fractionFadedIn = 1.0; + m_fadeAnimationType = FadeOutAnimation; + + startFadeAnimation(); +} + +void PageOverlay::startFadeAnimation() +{ + m_fadeAnimationStartTime = currentTime(); + + // Start the timer + m_fadeAnimationTimer.startRepeating(1 / fadeAnimationFrameRate); +} + +void PageOverlay::fadeAnimationTimerFired() +{ + float animationProgress = (currentTime() - m_fadeAnimationStartTime) / m_fadeAnimationDuration; + + if (animationProgress >= 1.0) + animationProgress = 1.0; + + double sine = sin(piOverTwoFloat * animationProgress); + float fadeAnimationValue = sine * sine; + + m_fractionFadedIn = (m_fadeAnimationType == FadeInAnimation) ? fadeAnimationValue : 1 - fadeAnimationValue; + setNeedsDisplay(); + + if (animationProgress == 1.0) { + m_fadeAnimationTimer.stop(); + + bool wasFadingOut = m_fadeAnimationType == FadeOutAnimation; + m_fadeAnimationType = NoAnimation; + + if (wasFadingOut) { + // If this was a fade out, go ahead and uninstall the page overlay. + m_webPage->uninstallPageOverlay(this, false); + } + } +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/PageOverlay.h b/Source/WebKit2/WebProcess/WebPage/PageOverlay.h new file mode 100644 index 000000000..1f61cebe9 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/PageOverlay.h @@ -0,0 +1,105 @@ +/* + * 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. + */ + +#ifndef PageOverlay_h +#define PageOverlay_h + +#include "APIObject.h" +#include "RunLoop.h" +#include <wtf/PassRefPtr.h> + +namespace WebCore { + class GraphicsContext; + class IntRect; +} + +namespace WebKit { + +class WebMouseEvent; +class WebPage; + +class PageOverlay : public APIObject { +public: + class Client { + protected: + virtual ~Client() { } + + public: + virtual void pageOverlayDestroyed(PageOverlay*) = 0; + virtual void willMoveToWebPage(PageOverlay*, WebPage*) = 0; + virtual void didMoveToWebPage(PageOverlay*, WebPage*) = 0; + virtual void drawRect(PageOverlay*, WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect) = 0; + virtual bool mouseEvent(PageOverlay*, const WebMouseEvent&) = 0; + }; + + static const Type APIType = TypeBundlePageOverlay; + + static PassRefPtr<PageOverlay> create(Client*); + virtual ~PageOverlay(); + + void setPage(WebPage*); + void setNeedsDisplay(const WebCore::IntRect& dirtyRect); + void setNeedsDisplay(); + + void drawRect(WebCore::GraphicsContext&, const WebCore::IntRect& dirtyRect); + bool mouseEvent(const WebMouseEvent&); + + void startFadeInAnimation(); + void startFadeOutAnimation(); + + float fractionFadedIn() const { return m_fractionFadedIn; } + +protected: + explicit PageOverlay(Client*); + +private: + // APIObject + virtual Type type() const { return APIType; } + + WebCore::IntRect bounds() const; + + void startFadeAnimation(); + void fadeAnimationTimerFired(); + + Client* m_client; + WebPage* m_webPage; + + RunLoop::Timer<PageOverlay> m_fadeAnimationTimer; + double m_fadeAnimationStartTime; + double m_fadeAnimationDuration; + + enum FadeAnimationType { + NoAnimation, + FadeInAnimation, + FadeOutAnimation, + }; + + FadeAnimationType m_fadeAnimationType; + float m_fractionFadedIn; +}; + +} // namespace WebKit + +#endif // PageOverlay_h diff --git a/Source/WebKit2/WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp b/Source/WebKit2/WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp new file mode 100644 index 000000000..4140e7279 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/TiledBackingStoreRemoteTile.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 "config.h" +#include "TiledBackingStoreRemoteTile.h" + +#if USE(TILED_BACKING_STORE) + +#include "GraphicsContext.h" +#include "ImageBuffer.h" +#include "TiledBackingStoreClient.h" +#include "UpdateInfo.h" + +using namespace WebCore; + +namespace WebKit { + +TiledBackingStoreRemoteTile::TiledBackingStoreRemoteTile(TiledBackingStoreRemoteTileClient* client, TiledBackingStore* tiledBackingStore, const Coordinate& tileCoordinate) + : m_client(client) + , m_tiledBackingStore(tiledBackingStore) + , m_coordinate(tileCoordinate) + , m_rect(tiledBackingStore->tileRectForCoordinate(tileCoordinate)) + , m_ID(0) + , m_dirtyRect(m_rect) +{ +} + +TiledBackingStoreRemoteTile::~TiledBackingStoreRemoteTile() +{ + if (m_ID) + m_client->removeTile(m_ID); +} + +bool TiledBackingStoreRemoteTile::isDirty() const +{ + return !m_dirtyRect.isEmpty(); +} + +void TiledBackingStoreRemoteTile::invalidate(const IntRect& dirtyRect) +{ + IntRect tileDirtyRect = intersection(dirtyRect, m_rect); + if (tileDirtyRect.isEmpty()) + return; + + m_dirtyRect.unite(tileDirtyRect); +} + +Vector<IntRect> TiledBackingStoreRemoteTile::updateBackBuffer() +{ + if (!isDirty()) + return Vector<IntRect>(); + + // FIXME: Only use a local buffer when we know the tile is animated (after the first invalidate) + // and destroy it after a few seconds of inactivity. We can render directly to shared + // memory in other cases. + if (!m_localBuffer || m_localBuffer->size() != m_rect.size()) { + m_localBuffer = ImageBuffer::create(m_rect.size()); + m_localBuffer->context()->translate(-m_rect.x(), -m_rect.y()); + m_localBuffer->context()->scale(FloatSize(m_tiledBackingStore->contentsScale(), m_tiledBackingStore->contentsScale())); + } + // This assumes that the GraphicsContext on the ImageBuffer acts synchronously + // for us to be able to draw this buffer on the ShareableBitmap right after. + m_tiledBackingStore->client()->tiledBackingStorePaint(m_localBuffer->context(), m_tiledBackingStore->mapToContents(m_dirtyRect)); + + RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(m_rect.size(), ShareableBitmap::SupportsAlpha); + OwnPtr<GraphicsContext> graphicsContext(bitmap->createGraphicsContext()); + graphicsContext->drawImageBuffer(m_localBuffer.get(), ColorSpaceDeviceRGB, IntPoint(0, 0)); + + UpdateInfo updateInfo; + updateInfo.updateRectBounds = m_rect; + updateInfo.updateScaleFactor = m_tiledBackingStore->contentsScale(); + bitmap->createHandle(updateInfo.bitmapHandle); + + static int id = 0; + if (!m_ID) { + m_ID = ++id; + m_client->createTile(m_ID, updateInfo); + } else + m_client->updateTile(m_ID, updateInfo); + + m_dirtyRect = IntRect(); + return Vector<IntRect>(); +} + +void TiledBackingStoreRemoteTile::swapBackBufferToFront() +{ + // Handled by tiledBackingStorePaintEnd. +} + +bool TiledBackingStoreRemoteTile::isReadyToPaint() const +{ + return !!m_ID; +} + +void TiledBackingStoreRemoteTile::paint(GraphicsContext* context, const IntRect& rect) +{ + ASSERT_NOT_REACHED(); +} + +void TiledBackingStoreRemoteTile::resize(const IntSize& newSize) +{ + m_rect = IntRect(m_rect.location(), newSize); + m_dirtyRect = m_rect; +} + +TiledBackingStoreRemoteTileBackend::TiledBackingStoreRemoteTileBackend(TiledBackingStoreRemoteTileClient* client) + : m_client(client) +{ +} + +PassRefPtr<WebCore::Tile> TiledBackingStoreRemoteTileBackend::createTile(WebCore::TiledBackingStore* tiledBackingStore, const WebCore::Tile::Coordinate& tileCoordinate) +{ + return TiledBackingStoreRemoteTile::create(m_client, tiledBackingStore, tileCoordinate); +} + +void TiledBackingStoreRemoteTileBackend::paintCheckerPattern(WebCore::GraphicsContext*, const WebCore::FloatRect&) +{ +} + +} // namespace WebKit + +#endif // USE(TILED_BACKING_STORE) diff --git a/Source/WebKit2/WebProcess/WebPage/TiledBackingStoreRemoteTile.h b/Source/WebKit2/WebProcess/WebPage/TiledBackingStoreRemoteTile.h new file mode 100644 index 000000000..12b2e0602 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/TiledBackingStoreRemoteTile.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. + */ + +#ifndef TiledBackingStoreRemoteTile_h +#define TiledBackingStoreRemoteTile_h + +#if USE(TILED_BACKING_STORE) + +#include "Tile.h" +#include "TiledBackingStore.h" +#include "WebCore/IntRect.h" + +namespace WebCore { +class ImageBuffer; +class TiledBackingStore; +} + +namespace WebKit { + +class TiledBackingStoreRemoteTileClient; +class UpdateInfo; + +class TiledBackingStoreRemoteTile : public WebCore::Tile { +public: + static PassRefPtr<Tile> create(TiledBackingStoreRemoteTileClient* client, WebCore::TiledBackingStore* tiledBackingStore, const Coordinate& tileCoordinate) { return adoptRef(new TiledBackingStoreRemoteTile(client, tiledBackingStore, tileCoordinate)); } + ~TiledBackingStoreRemoteTile(); + + bool isDirty() const; + void invalidate(const WebCore::IntRect&); + Vector<WebCore::IntRect> updateBackBuffer(); + void swapBackBufferToFront(); + bool isReadyToPaint() const; + void paint(WebCore::GraphicsContext*, const WebCore::IntRect&); + + const Coordinate& coordinate() const { return m_coordinate; } + const WebCore::IntRect& rect() const { return m_rect; } + void resize(const WebCore::IntSize&); + +private: + TiledBackingStoreRemoteTile(TiledBackingStoreRemoteTileClient*, WebCore::TiledBackingStore*, const Coordinate&); + + TiledBackingStoreRemoteTileClient* m_client; + WebCore::TiledBackingStore* m_tiledBackingStore; + Coordinate m_coordinate; + WebCore::IntRect m_rect; + + int m_ID; + WebCore::IntRect m_dirtyRect; + + OwnPtr<WebCore::ImageBuffer> m_localBuffer; +}; + +class TiledBackingStoreRemoteTileClient { +public: + virtual ~TiledBackingStoreRemoteTileClient() { } + virtual void createTile(int tileID, const UpdateInfo&) = 0; + virtual void updateTile(int tileID, const UpdateInfo&) = 0; + virtual void removeTile(int tileID) = 0; +}; + +class TiledBackingStoreRemoteTileBackend : public WebCore::TiledBackingStoreBackend { +public: + static PassOwnPtr<WebCore::TiledBackingStoreBackend> create(TiledBackingStoreRemoteTileClient* client) { return adoptPtr(new TiledBackingStoreRemoteTileBackend(client)); } + PassRefPtr<WebCore::Tile> createTile(WebCore::TiledBackingStore*, const WebCore::Tile::Coordinate&); + void paintCheckerPattern(WebCore::GraphicsContext*, const WebCore::FloatRect&); + +private: + TiledBackingStoreRemoteTileBackend(TiledBackingStoreRemoteTileClient*); + TiledBackingStoreRemoteTileClient* m_client; +}; + + +} // namespace WebKit + +#endif // USE(TILED_BACKING_STORE) + +#endif // TiledBackingStoreRemoteTile diff --git a/Source/WebKit2/WebProcess/WebPage/TiledDrawingArea.cpp b/Source/WebKit2/WebProcess/WebPage/TiledDrawingArea.cpp new file mode 100644 index 000000000..c482e664b --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/TiledDrawingArea.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 "config.h" +#include "TiledDrawingArea.h" + +#if USE(TILED_BACKING_STORE) + +#include "DrawingAreaProxyMessages.h" +#include "MessageID.h" +#include "UpdateInfo.h" +#include "WebCoreArgumentCoders.h" +#include "WebPage.h" +#include "WebProcess.h" + +using namespace WebCore; + +namespace WebKit { + +TiledDrawingArea::TiledDrawingArea(WebPage* webPage) + : DrawingArea(DrawingAreaTypeTiled, webPage) + , m_suspended(false) + , m_isWaitingForUIProcess(false) + , m_didSendTileUpdate(false) + , m_mainBackingStore(adoptPtr(new TiledBackingStore(this, TiledBackingStoreRemoteTileBackend::create(this)))) +{ +} + +TiledDrawingArea::~TiledDrawingArea() +{ +} + +void TiledDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollDelta) +{ + // FIXME: Do something much smarter. + setNeedsDisplay(scrollRect); +} + +void TiledDrawingArea::setNeedsDisplay(const IntRect& rect) +{ + m_mainBackingStore->invalidate(rect); +} + +void TiledDrawingArea::setSize(const IntSize& viewSize) +{ + ASSERT(!m_suspended); + ASSERT_ARG(viewSize, !viewSize.isEmpty()); + + m_webPage->setSize(viewSize); +} + +void TiledDrawingArea::setVisibleContentRectAndScale(const WebCore::IntRect& visibleContentsRect, float scale) +{ + m_visibleContentRect = visibleContentsRect; + + if (scale != m_mainBackingStore->contentsScale()) { + // Keep the tiles for the previous scale until enough content is available to be shown on the screen for the new scale. + // If we already have a previous set of tiles it means that two scale changed happened successively. + // In that case, make sure that our current main tiles have more content to show than the "previous previous" + // within the visible rect before replacing it. + if (!m_previousBackingStore || m_mainBackingStore->coverageRatio(m_visibleContentRect) > m_previousBackingStore->coverageRatio(m_visibleContentRect)) + m_previousBackingStore = m_mainBackingStore.release(); + + m_mainBackingStore = adoptPtr(new TiledBackingStore(this, TiledBackingStoreRemoteTileBackend::create(this))); + m_mainBackingStore->setContentsScale(scale); + } else + m_mainBackingStore->adjustVisibleRect(); +} + +void TiledDrawingArea::setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint& trajectoryVector) +{ + m_mainBackingStore->setVisibleRectTrajectoryVector(trajectoryVector); +} + +void TiledDrawingArea::renderNextFrame() +{ + m_isWaitingForUIProcess = false; + m_mainBackingStore->updateTileBuffers(); +} + +void TiledDrawingArea::suspendPainting() +{ + ASSERT(!m_suspended); + + m_suspended = true; +} + +void TiledDrawingArea::resumePainting() +{ + ASSERT(m_suspended); + + m_suspended = false; + m_mainBackingStore->updateTileBuffers(); +} + +void TiledDrawingArea::tiledBackingStorePaintBegin() +{ + m_webPage->layoutIfNeeded(); +} + +void TiledDrawingArea::tiledBackingStorePaint(GraphicsContext* graphicsContext, const IntRect& contentRect) +{ + m_webPage->drawRect(*graphicsContext, contentRect); +} + +void TiledDrawingArea::tiledBackingStorePaintEnd(const Vector<IntRect>& paintedArea) +{ + if (m_didSendTileUpdate) { + // Since we know that all tile updates following a page invalidate will all be rendered + // in one paint pass for all the tiles, we can send the swap tile message here. + m_webPage->send(Messages::DrawingAreaProxy::DidRenderFrame()); + m_isWaitingForUIProcess = true; + m_didSendTileUpdate = false; + + // Make sure that we destroy the previous backing store and remove its tiles only after DidRenderFrame + // was sent to swap recently created tiles' buffer. Else a frame could be rendered after the previous + // tiles were removed and before the new tile have their first back buffer swapped. + if (m_previousBackingStore && m_mainBackingStore->coverageRatio(m_visibleContentRect) >= 1.0f) + m_previousBackingStore.clear(); + } +} + +bool TiledDrawingArea::tiledBackingStoreUpdatesAllowed() const +{ + return !m_suspended && !m_isWaitingForUIProcess; +} + +IntRect TiledDrawingArea::tiledBackingStoreContentsRect() +{ + return IntRect(IntPoint::zero(), m_webPage->size()); +} + +IntRect TiledDrawingArea::tiledBackingStoreVisibleRect() +{ + return m_visibleContentRect; +} + +Color TiledDrawingArea::tiledBackingStoreBackgroundColor() const +{ + return Color::transparent; +} + +void TiledDrawingArea::createTile(int tileID, const UpdateInfo& updateInfo) +{ + m_webPage->send(Messages::DrawingAreaProxy::CreateTile(tileID, updateInfo)); + m_didSendTileUpdate = true; +} +void TiledDrawingArea::updateTile(int tileID, const UpdateInfo& updateInfo) +{ + m_webPage->send(Messages::DrawingAreaProxy::UpdateTile(tileID, updateInfo)); + m_didSendTileUpdate = true; +} +void TiledDrawingArea::removeTile(int tileID) +{ + m_webPage->send(Messages::DrawingAreaProxy::RemoveTile(tileID)); +} + +#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) +void TiledDrawingArea::didReceiveLayerTreeHostMessage(CoreIPC::Connection* connection, CoreIPC::MessageID, CoreIPC::ArgumentDecoder* arguments) +{ +} +#endif +} // namespace WebKit + +#endif // USE(TILED_BACKING_STORE) diff --git a/Source/WebKit2/WebProcess/WebPage/TiledDrawingArea.h b/Source/WebKit2/WebProcess/WebPage/TiledDrawingArea.h new file mode 100644 index 000000000..cbcbd3090 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/TiledDrawingArea.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. + */ + +#ifndef TiledDrawingArea_h +#define TiledDrawingArea_h + +#if USE(TILED_BACKING_STORE) + +#include "DrawingArea.h" +#include "TiledBackingStoreClient.h" +#include "TiledBackingStoreRemoteTile.h" +#include <WebCore/IntRect.h> + +namespace WebKit { + +class TiledDrawingArea : public DrawingArea, public WebCore::TiledBackingStoreClient, public TiledBackingStoreRemoteTileClient { +public: + explicit TiledDrawingArea(WebPage*); + virtual ~TiledDrawingArea(); + + virtual void setNeedsDisplay(const WebCore::IntRect&); + virtual void scroll(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollDelta); + +#if USE(ACCELERATED_COMPOSITING) + virtual void attachCompositingContext() { } + virtual void detachCompositingContext() { } + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) { } + virtual void scheduleCompositingLayerSync() { } + virtual void didReceiveLayerTreeHostMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); +#endif + +private: + // CoreIPC message handlers. + virtual void setSize(const WebCore::IntSize& viewSize); + virtual void setVisibleContentRectAndScale(const WebCore::IntRect&, float); + virtual void setVisibleContentRectTrajectoryVector(const WebCore::FloatPoint&); + virtual void renderNextFrame(); + virtual void suspendPainting(); + virtual void resumePainting(); + + // TiledBackingStoreClient + virtual void tiledBackingStorePaintBegin(); + virtual void tiledBackingStorePaint(WebCore::GraphicsContext*, const WebCore::IntRect& contentRect); + virtual void tiledBackingStorePaintEnd(const Vector<WebCore::IntRect>& paintedArea); + virtual bool tiledBackingStoreUpdatesAllowed() const; + virtual WebCore::IntRect tiledBackingStoreContentsRect(); + virtual WebCore::IntRect tiledBackingStoreVisibleRect(); + virtual WebCore::Color tiledBackingStoreBackgroundColor() const; + + // TiledBackingStoreRemoteTileClient + virtual void createTile(int tileID, const UpdateInfo&); + virtual void updateTile(int tileID, const UpdateInfo&); + virtual void removeTile(int tileID); + + bool m_suspended; + bool m_isWaitingForUIProcess; + bool m_didSendTileUpdate; + WebCore::IntRect m_visibleContentRect; + + OwnPtr<WebCore::TiledBackingStore> m_mainBackingStore; + OwnPtr<WebCore::TiledBackingStore> m_previousBackingStore; +}; + +} // namespace WebKit + +#endif // USE(TILED_BACKING_STORE) + +#endif // TiledDrawingArea_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebBackForwardListProxy.cpp b/Source/WebKit2/WebProcess/WebPage/WebBackForwardListProxy.cpp new file mode 100644 index 000000000..7a6045eb6 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebBackForwardListProxy.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2010, 2011 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 "config.h" +#include "WebBackForwardListProxy.h" + +#include "DataReference.h" +#include "EncoderAdapter.h" +#include "WebCoreArgumentCoders.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include "WebProcess.h" +#include "WebProcessProxyMessages.h" +#include <WebCore/HistoryItem.h> +#include <wtf/HashMap.h> + +using namespace WebCore; + +namespace WebKit { + +static const unsigned DefaultCapacity = 100; +static const unsigned NoCurrentItemIndex = UINT_MAX; + +// FIXME <rdar://problem/8819268>: This leaks all HistoryItems that go into these maps. +// We need to clear up the life time of these objects. + +typedef HashMap<uint64_t, RefPtr<HistoryItem> > IDToHistoryItemMap; +typedef HashMap<RefPtr<HistoryItem>, uint64_t> HistoryItemToIDMap; + +static IDToHistoryItemMap& idToHistoryItemMap() +{ + DEFINE_STATIC_LOCAL(IDToHistoryItemMap, map, ()); + return map; +} + +static HistoryItemToIDMap& historyItemToIDMap() +{ + DEFINE_STATIC_LOCAL(HistoryItemToIDMap, map, ()); + return map; +} + +static uint64_t uniqueHistoryItemID = 1; + +static uint64_t generateHistoryItemID() +{ + // These IDs exist in the WebProcess for items created by the WebProcess. + // The IDs generated here need to never collide with the IDs created in WebBackForwardList in the UIProcess. + // We accomplish this by starting from 3, and only ever using odd ids. + uniqueHistoryItemID += 2; + return uniqueHistoryItemID; +} + +void WebBackForwardListProxy::setHighestItemIDFromUIProcess(uint64_t itemID) +{ + if (itemID <= uniqueHistoryItemID) + return; + + if (itemID % 2) + uniqueHistoryItemID = itemID; + else + uniqueHistoryItemID = itemID + 1; +} + +static void updateBackForwardItem(uint64_t itemID, HistoryItem* item) +{ + EncoderAdapter encoder; + item->encodeBackForwardTree(encoder); + + WebProcess::shared().connection()->send(Messages::WebProcessProxy::AddBackForwardItem(itemID, item->originalURLString(), item->urlString(), item->title(), encoder.dataReference()), 0); +} + +void WebBackForwardListProxy::addItemFromUIProcess(uint64_t itemID, PassRefPtr<WebCore::HistoryItem> prpItem) +{ + RefPtr<HistoryItem> item = prpItem; + + // This item/itemID pair should not already exist in our maps. + ASSERT(!historyItemToIDMap().contains(item.get())); + ASSERT(!idToHistoryItemMap().contains(itemID)); + + historyItemToIDMap().set(item, itemID); + idToHistoryItemMap().set(itemID, item); +} + +static void WK2NotifyHistoryItemChanged(HistoryItem* item) +{ + uint64_t itemID = historyItemToIDMap().get(item); + if (!itemID) + return; + + updateBackForwardItem(itemID, item); +} + +HistoryItem* WebBackForwardListProxy::itemForID(uint64_t itemID) +{ + return idToHistoryItemMap().get(itemID).get(); +} + +uint64_t WebBackForwardListProxy::idForItem(HistoryItem* item) +{ + ASSERT(item); + return historyItemToIDMap().get(item); +} + +void WebBackForwardListProxy::removeItem(uint64_t itemID) +{ + IDToHistoryItemMap::iterator it = idToHistoryItemMap().find(itemID); + if (it == idToHistoryItemMap().end()) + return; + historyItemToIDMap().remove(it->second); + idToHistoryItemMap().remove(it); +} + +WebBackForwardListProxy::WebBackForwardListProxy(WebPage* page) + : m_page(page) +{ + WebCore::notifyHistoryItemChanged = WK2NotifyHistoryItemChanged; +} + +void WebBackForwardListProxy::addItem(PassRefPtr<HistoryItem> prpItem) +{ + RefPtr<HistoryItem> item = prpItem; + + ASSERT(!historyItemToIDMap().contains(item)); + + if (!m_page) + return; + + uint64_t itemID = generateHistoryItemID(); + + ASSERT(!idToHistoryItemMap().contains(itemID)); + + historyItemToIDMap().set(item, itemID); + idToHistoryItemMap().set(itemID, item); + + updateBackForwardItem(itemID, item.get()); + m_page->send(Messages::WebPageProxy::BackForwardAddItem(itemID)); +} + +void WebBackForwardListProxy::goToItem(HistoryItem* item) +{ + if (!m_page) + return; + + m_page->send(Messages::WebPageProxy::BackForwardGoToItem(historyItemToIDMap().get(item))); +} + +HistoryItem* WebBackForwardListProxy::itemAtIndex(int itemIndex) +{ + if (!m_page) + return 0; + + uint64_t itemID = 0; + if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::BackForwardItemAtIndex(itemIndex), Messages::WebPageProxy::BackForwardItemAtIndex::Reply(itemID), m_page->pageID())) + return 0; + + if (!itemID) + return 0; + + return idToHistoryItemMap().get(itemID).get(); +} + +int WebBackForwardListProxy::backListCount() +{ + if (!m_page) + return 0; + + int backListCount = 0; + if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::BackForwardBackListCount(), Messages::WebPageProxy::BackForwardBackListCount::Reply(backListCount), m_page->pageID())) + return 0; + + return backListCount; +} + +int WebBackForwardListProxy::forwardListCount() +{ + if (!m_page) + return 0; + + int forwardListCount = 0; + if (!WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::BackForwardForwardListCount(), Messages::WebPageProxy::BackForwardForwardListCount::Reply(forwardListCount), m_page->pageID())) + return 0; + + return forwardListCount; +} + +void WebBackForwardListProxy::close() +{ + m_page = 0; +} + +bool WebBackForwardListProxy::isActive() +{ + // FIXME: Should check the the list is enabled and has non-zero capacity. + return true; +} + +void WebBackForwardListProxy::clear() +{ + m_page->send(Messages::WebPageProxy::BackForwardClear()); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebBackForwardListProxy.h b/Source/WebKit2/WebProcess/WebPage/WebBackForwardListProxy.h new file mode 100644 index 000000000..b69eb123d --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebBackForwardListProxy.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010, 2011 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. + */ + +#ifndef WebBackForwardListProxy_h +#define WebBackForwardListProxy_h + +#include <WebCore/BackForwardList.h> +#include <wtf/PassRefPtr.h> + +namespace WebKit { + +class WebPage; + +class WebBackForwardListProxy : public WebCore::BackForwardList { +public: + static PassRefPtr<WebBackForwardListProxy> create(WebPage* page) { return adoptRef(new WebBackForwardListProxy(page)); } + + static WebCore::HistoryItem* itemForID(uint64_t); + static uint64_t idForItem(WebCore::HistoryItem*); + static void removeItem(uint64_t itemID); + + static void addItemFromUIProcess(uint64_t itemID, PassRefPtr<WebCore::HistoryItem>); + static void setHighestItemIDFromUIProcess(uint64_t itemID); + + void clear(); + +private: + WebBackForwardListProxy(WebPage*); + + virtual void addItem(PassRefPtr<WebCore::HistoryItem>); + + virtual void goToItem(WebCore::HistoryItem*); + + virtual WebCore::HistoryItem* itemAtIndex(int); + virtual int backListCount(); + virtual int forwardListCount(); + + virtual bool isActive(); + + virtual void close(); + + WebPage* m_page; +}; + +} // namespace WebKit + +#endif // WebBackForwardListProxy_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp b/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp new file mode 100644 index 000000000..e7e2e745f --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebContextMenu.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "WebContextMenu.h" + +#include "ContextMenuState.h" +#include "InjectedBundleHitTestResult.h" +#include "InjectedBundleUserMessageCoders.h" +#include "WebCoreArgumentCoders.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include "WebProcess.h" +#include <WebCore/ContextMenu.h> +#include <WebCore/ContextMenuController.h> +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/Page.h> + +using namespace WebCore; + +namespace WebKit { + +WebContextMenu::WebContextMenu(WebPage* page) + : m_page(page) +{ +} + +WebContextMenu::~WebContextMenu() +{ +} + +void WebContextMenu::show() +{ + ContextMenuController* controller = m_page->corePage()->contextMenuController(); + if (!controller) + return; + ContextMenu* menu = controller->contextMenu(); + if (!menu) + return; + Node* node = controller->hitTestResult().innerNonSharedNode(); + if (!node) + return; + Frame* frame = node->document()->frame(); + if (!frame) + return; + FrameView* view = frame->view(); + if (!view) + return; + + // Give the bundle client a chance to process the menu. +#if USE(CROSS_PLATFORM_CONTEXT_MENUS) + const Vector<ContextMenuItem>& coreItems = menu->items(); +#else + Vector<ContextMenuItem> coreItems = contextMenuItemVector(menu->platformDescription()); +#endif + Vector<WebContextMenuItemData> proposedMenu = kitItems(coreItems, menu); + Vector<WebContextMenuItemData> newMenu; + RefPtr<APIObject> userData; + RefPtr<InjectedBundleHitTestResult> hitTestResult = InjectedBundleHitTestResult::create(controller->hitTestResult()); + if (m_page->injectedBundleContextMenuClient().getCustomMenuFromDefaultItems(m_page, hitTestResult.get(), proposedMenu, newMenu, userData)) + proposedMenu = newMenu; + + ContextMenuState contextMenuState; + contextMenuState.absoluteImageURLString = controller->hitTestResult().absoluteImageURL().string(); + contextMenuState.absoluteLinkURLString = controller->hitTestResult().absoluteLinkURL().string(); + + // Mark the WebPage has having a shown context menu then notify the UIProcess. + m_page->contextMenuShowing(); + m_page->send(Messages::WebPageProxy::ShowContextMenu(view->contentsToWindow(controller->hitTestResult().point()), contextMenuState, proposedMenu, InjectedBundleUserMessageEncoder(userData.get()))); +} + +void WebContextMenu::itemSelected(const WebContextMenuItemData& item) +{ + ContextMenuItem coreItem(ActionType, static_cast<ContextMenuAction>(item.action()), item.title()); + m_page->corePage()->contextMenuController()->contextMenuItemSelected(&coreItem); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebContextMenu.h b/Source/WebKit2/WebProcess/WebPage/WebContextMenu.h new file mode 100644 index 000000000..3d9291aa3 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebContextMenu.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WebContextMenu_h +#define WebContextMenu_h + +#include "WebContextMenuItemData.h" + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace WebKit { + +class WebPage; + +class WebContextMenu : public RefCounted<WebContextMenu> { +public: + static PassRefPtr<WebContextMenu> create(WebPage* page) + { + return adoptRef(new WebContextMenu(page)); + } + + ~WebContextMenu(); + + void show(); + void itemSelected(const WebContextMenuItemData&); + +private: + WebContextMenu(WebPage*); + + WebPage* m_page; +}; + +} // namespace WebKit + +#endif // WebPopupMenu_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp new file mode 100644 index 000000000..b32543eee --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebFrame.cpp @@ -0,0 +1,738 @@ +/* + * 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 "config.h" +#include "WebFrame.h" + +#include "DownloadManager.h" +#include "InjectedBundleNodeHandle.h" +#include "InjectedBundleRangeHandle.h" +#include "InjectedBundleScriptWorld.h" +#include "WebChromeClient.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include "WebProcess.h" +#include <JavaScriptCore/APICast.h> +#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSLock.h> +#include <JavaScriptCore/JSValueRef.h> +#include <WebCore/AnimationController.h> +#include <WebCore/ArchiveResource.h> +#include <WebCore/CSSComputedStyleDeclaration.h> +#include <WebCore/Chrome.h> +#include <WebCore/DocumentLoader.h> +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/HTMLFrameOwnerElement.h> +#include <WebCore/HTMLNames.h> +#include <WebCore/JSCSSStyleDeclaration.h> +#include <WebCore/JSElement.h> +#include <WebCore/JSRange.h> +#include <WebCore/Page.h> +#include <WebCore/RenderTreeAsText.h> +#include <WebCore/SecurityOrigin.h> +#include <WebCore/TextIterator.h> +#include <WebCore/TextResourceDecoder.h> +#include <wtf/text/StringBuilder.h> + +#if PLATFORM(MAC) || PLATFORM(WIN) +#include <WebCore/LegacyWebArchive.h> +#endif + +#ifndef NDEBUG +#include <wtf/RefCountedLeakCounter.h> +#endif + +using namespace JSC; +using namespace WebCore; + +namespace WebKit { + +DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webFrameCounter, ("WebFrame")); + +static uint64_t generateFrameID() +{ + static uint64_t uniqueFrameID = 1; + return uniqueFrameID++; +} + +static uint64_t generateListenerID() +{ + static uint64_t uniqueListenerID = 1; + return uniqueListenerID++; +} + +PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page) +{ + RefPtr<WebFrame> frame = create(); + + page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID())); + + frame->init(page, String(), 0); + + return frame.release(); +} + +PassRefPtr<WebFrame> WebFrame::createSubframe(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement) +{ + RefPtr<WebFrame> frame = create(); + + WebFrame* parentFrame = static_cast<WebFrameLoaderClient*>(ownerElement->document()->frame()->loader()->client())->webFrame(); + page->send(Messages::WebPageProxy::DidCreateSubframe(frame->frameID(), parentFrame->frameID())); + + frame->init(page, frameName, ownerElement); + + return frame.release(); +} + +PassRefPtr<WebFrame> WebFrame::create() +{ + RefPtr<WebFrame> frame = adoptRef(new WebFrame); + + // Add explict ref() that will be balanced in WebFrameLoaderClient::frameLoaderDestroyed(). + frame->ref(); + + return frame.release(); +} + +WebFrame::WebFrame() + : m_coreFrame(0) + , m_policyListenerID(0) + , m_policyFunction(0) + , m_policyDownloadID(0) + , m_frameLoaderClient(this) + , m_loadListener(0) + , m_frameID(generateFrameID()) +{ + WebProcess::shared().addWebFrame(m_frameID, this); + +#ifndef NDEBUG + webFrameCounter.increment(); +#endif +} + +WebFrame::~WebFrame() +{ + ASSERT(!m_coreFrame); + +#ifndef NDEBUG + webFrameCounter.decrement(); +#endif +} + +void WebFrame::init(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement) +{ + RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient); + m_coreFrame = frame.get(); + + frame->tree()->setName(frameName); + + if (ownerElement) { + ASSERT(ownerElement->document()->frame()); + ownerElement->document()->frame()->tree()->appendChild(frame); + } + + frame->init(); +} + +WebPage* WebFrame::page() const +{ + if (!m_coreFrame) + return 0; + + if (WebCore::Page* page = m_coreFrame->page()) + return static_cast<WebChromeClient*>(page->chrome()->client())->page(); + + return 0; +} + +void WebFrame::invalidate() +{ + WebProcess::shared().removeWebFrame(m_frameID); + m_coreFrame = 0; +} + +uint64_t WebFrame::setUpPolicyListener(WebCore::FramePolicyFunction policyFunction) +{ + // FIXME: <rdar://5634381> We need to support multiple active policy listeners. + + invalidatePolicyListener(); + + m_policyListenerID = generateListenerID(); + m_policyFunction = policyFunction; + return m_policyListenerID; +} + +void WebFrame::invalidatePolicyListener() +{ + if (!m_policyListenerID) + return; + + m_policyDownloadID = 0; + m_policyListenerID = 0; + m_policyFunction = 0; +} + +void WebFrame::didReceivePolicyDecision(uint64_t listenerID, PolicyAction action, uint64_t downloadID) +{ + if (!m_coreFrame) + return; + + if (!m_policyListenerID) + return; + + if (listenerID != m_policyListenerID) + return; + + ASSERT(m_policyFunction); + + FramePolicyFunction function = m_policyFunction; + + invalidatePolicyListener(); + + m_policyDownloadID = downloadID; + + (m_coreFrame->loader()->policyChecker()->*function)(action); +} + +void WebFrame::startDownload(const WebCore::ResourceRequest& request) +{ + ASSERT(m_policyDownloadID); + + DownloadManager::shared().startDownload(m_policyDownloadID, page(), request); + + m_policyDownloadID = 0; +} + +void WebFrame::convertHandleToDownload(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& response) +{ + ASSERT(m_policyDownloadID); + + DownloadManager::shared().convertHandleToDownload(m_policyDownloadID, page(), handle, request, response); + m_policyDownloadID = 0; +} + +String WebFrame::source() const +{ + if (!m_coreFrame) + return String(); + Document* document = m_coreFrame->document(); + if (!document) + return String(); + TextResourceDecoder* decoder = document->decoder(); + if (!decoder) + return String(); + DocumentLoader* documentLoader = m_coreFrame->loader()->activeDocumentLoader(); + if (!documentLoader) + return String(); + RefPtr<SharedBuffer> mainResourceData = documentLoader->mainResourceData(); + if (!mainResourceData) + return String(); + return decoder->encoding().decode(mainResourceData->data(), mainResourceData->size()); +} + +String WebFrame::contentsAsString() const +{ + if (!m_coreFrame) + return String(); + + if (isFrameSet()) { + StringBuilder builder; + for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { + if (!builder.isEmpty()) + builder.append(' '); + builder.append(static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame()->contentsAsString()); + } + // FIXME: It may make sense to use toStringPreserveCapacity() here. + return builder.toString(); + } + + Document* document = m_coreFrame->document(); + if (!document) + return String(); + + RefPtr<Element> documentElement = document->documentElement(); + if (!documentElement) + return String(); + + RefPtr<Range> range = document->createRange(); + + ExceptionCode ec = 0; + range->selectNode(documentElement.get(), ec); + if (ec) + return String(); + + return plainText(range.get()); +} + +String WebFrame::selectionAsString() const +{ + if (!m_coreFrame) + return String(); + + return m_coreFrame->displayStringModifiedByEncoding(m_coreFrame->editor()->selectedText()); +} + +IntSize WebFrame::size() const +{ + if (!m_coreFrame) + return IntSize(); + + FrameView* frameView = m_coreFrame->view(); + if (!frameView) + return IntSize(); + + return frameView->contentsSize(); +} + +bool WebFrame::isFrameSet() const +{ + if (!m_coreFrame) + return false; + + Document* document = m_coreFrame->document(); + if (!document) + return false; + return document->isFrameSet(); +} + +bool WebFrame::isMainFrame() const +{ + if (WebPage* p = page()) + return p->mainWebFrame() == this; + + return false; +} + +String WebFrame::name() const +{ + if (!m_coreFrame) + return String(); + + return m_coreFrame->tree()->uniqueName(); +} + +String WebFrame::url() const +{ + if (!m_coreFrame) + return String(); + + DocumentLoader* documentLoader = m_coreFrame->loader()->documentLoader(); + if (!documentLoader) + return String(); + + return documentLoader->url().string(); +} + +String WebFrame::innerText() const +{ + if (!m_coreFrame) + return String(); + + if (!m_coreFrame->document()->documentElement()) + return String(); + + return m_coreFrame->document()->documentElement()->innerText(); +} + +PassRefPtr<ImmutableArray> WebFrame::childFrames() +{ + if (!m_coreFrame) + return ImmutableArray::create(); + + size_t size = m_coreFrame->tree()->childCount(); + if (!size) + return ImmutableArray::create(); + + Vector<RefPtr<APIObject> > vector; + vector.reserveInitialCapacity(size); + + for (Frame* child = m_coreFrame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { + WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(child->loader()->client())->webFrame(); + vector.uncheckedAppend(webFrame); + } + + return ImmutableArray::adopt(vector); +} + +unsigned WebFrame::numberOfActiveAnimations() const +{ + if (!m_coreFrame) + return 0; + + AnimationController* controller = m_coreFrame->animation(); + if (!controller) + return 0; + + return controller->numberOfActiveAnimations(m_coreFrame->document()); +} + +bool WebFrame::pauseAnimationOnElementWithId(const String& animationName, const String& elementID, double time) +{ + if (!m_coreFrame) + return false; + + AnimationController* controller = m_coreFrame->animation(); + if (!controller) + return false; + + if (!m_coreFrame->document()) + return false; + + Node* coreNode = m_coreFrame->document()->getElementById(elementID); + if (!coreNode || !coreNode->renderer()) + return false; + + return controller->pauseAnimationAtTime(coreNode->renderer(), animationName, time); +} + +bool WebFrame::pauseTransitionOnElementWithId(const String& propertyName, const String& elementID, double time) +{ + if (!m_coreFrame) + return false; + + AnimationController* controller = m_coreFrame->animation(); + if (!controller) + return false; + + if (!m_coreFrame->document()) + return false; + + Node* coreNode = m_coreFrame->document()->getElementById(elementID); + if (!coreNode || !coreNode->renderer()) + return false; + + return controller->pauseTransitionAtTime(coreNode->renderer(), propertyName, time); +} + +void WebFrame::suspendAnimations() +{ + if (!m_coreFrame) + return; + + AnimationController* controller = m_coreFrame->animation(); + if (!controller) + return; + + controller->suspendAnimations(); +} + +void WebFrame::resumeAnimations() +{ + if (!m_coreFrame) + return; + + AnimationController* controller = m_coreFrame->animation(); + if (!controller) + return; + + controller->resumeAnimations(); +} + +String WebFrame::layerTreeAsText() const +{ + if (!m_coreFrame) + return ""; + + return m_coreFrame->layerTreeAsText(); +} + +unsigned WebFrame::pendingUnloadCount() const +{ + if (!m_coreFrame) + return 0; + + return m_coreFrame->domWindow()->pendingUnloadEventListeners(); +} + +bool WebFrame::allowsFollowingLink(const WebCore::KURL& url) const +{ + if (!m_coreFrame) + return true; + + return m_coreFrame->document()->securityOrigin()->canDisplay(url); +} + +JSGlobalContextRef WebFrame::jsContext() +{ + return toGlobalRef(m_coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()); +} + +JSGlobalContextRef WebFrame::jsContextForWorld(InjectedBundleScriptWorld* world) +{ + return toGlobalRef(m_coreFrame->script()->globalObject(world->coreWorld())->globalExec()); +} + +IntRect WebFrame::contentBounds() const +{ + if (!m_coreFrame) + return IntRect(); + + FrameView* view = m_coreFrame->view(); + if (!view) + return IntRect(); + + return IntRect(0, 0, view->contentsWidth(), view->contentsHeight()); +} + +IntRect WebFrame::visibleContentBounds() const +{ + if (!m_coreFrame) + return IntRect(); + + FrameView* view = m_coreFrame->view(); + if (!view) + return IntRect(); + + IntRect contentRect = view->visibleContentRect(true); + return IntRect(0, 0, contentRect.width(), contentRect.height()); +} + +IntRect WebFrame::visibleContentBoundsExcludingScrollbars() const +{ + if (!m_coreFrame) + return IntRect(); + + FrameView* view = m_coreFrame->view(); + if (!view) + return IntRect(); + + IntRect contentRect = view->visibleContentRect(false); + return IntRect(0, 0, contentRect.width(), contentRect.height()); +} + +IntSize WebFrame::scrollOffset() const +{ + if (!m_coreFrame) + return IntSize(); + + FrameView* view = m_coreFrame->view(); + if (!view) + return IntSize(); + + return view->scrollOffset(); +} + +bool WebFrame::hasHorizontalScrollbar() const +{ + if (!m_coreFrame) + return false; + + FrameView* view = m_coreFrame->view(); + if (!view) + return false; + + return view->horizontalScrollbar(); +} + +bool WebFrame::hasVerticalScrollbar() const +{ + if (!m_coreFrame) + return false; + + FrameView* view = m_coreFrame->view(); + if (!view) + return false; + + return view->verticalScrollbar(); +} + +bool WebFrame::getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha) +{ + if (!m_coreFrame) + return false; + + FrameView* view = m_coreFrame->view(); + if (!view) + return false; + + Color bgColor = view->documentBackgroundColor(); + if (!bgColor.isValid()) + return false; + + bgColor.getRGBA(*red, *green, *blue, *alpha); + return true; +} + +bool WebFrame::containsAnyFormElements() const +{ + if (!m_coreFrame) + return false; + + Document* document = m_coreFrame->document(); + if (!document) + return false; + + for (Node* node = document->documentElement(); node; node = node->traverseNextNode()) { + if (!node->isElementNode()) + continue; + if (static_cast<Element*>(node)->hasTagName(HTMLNames::formTag)) + return true; + } + return false; +} + +WebFrame* WebFrame::frameForContext(JSContextRef context) +{ + JSObjectRef globalObjectRef = JSContextGetGlobalObject(context); + JSC::JSObject* globalObjectObj = toJS(globalObjectRef); + if (strcmp(globalObjectObj->classInfo()->className, "JSDOMWindowShell") != 0) + return 0; + + Frame* coreFrame = static_cast<JSDOMWindowShell*>(globalObjectObj)->window()->impl()->frame(); + return static_cast<WebFrameLoaderClient*>(coreFrame->loader()->client())->webFrame(); +} + +JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleNodeHandle* nodeHandle, InjectedBundleScriptWorld* world) +{ + if (!m_coreFrame) + return 0; + + JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld()); + ExecState* exec = globalObject->globalExec(); + + JSLock lock(SilenceAssertionsOnly); + return toRef(exec, toJS(exec, globalObject, nodeHandle->coreNode())); +} + +JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleRangeHandle* rangeHandle, InjectedBundleScriptWorld* world) +{ + if (!m_coreFrame) + return 0; + + JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(world->coreWorld()); + ExecState* exec = globalObject->globalExec(); + + JSLock lock(SilenceAssertionsOnly); + return toRef(exec, toJS(exec, globalObject, rangeHandle->coreRange())); +} + +JSValueRef WebFrame::computedStyleIncludingVisitedInfo(JSObjectRef element) +{ + if (!m_coreFrame) + return 0; + + JSDOMWindow* globalObject = m_coreFrame->script()->globalObject(mainThreadNormalWorld()); + ExecState* exec = globalObject->globalExec(); + + if (!toJS(element)->inherits(&JSElement::s_info)) + return JSValueMakeUndefined(toRef(exec)); + + RefPtr<CSSComputedStyleDeclaration> style = computedStyle(static_cast<JSElement*>(toJS(element))->impl(), true); + + JSLock lock(SilenceAssertionsOnly); + return toRef(exec, toJS(exec, globalObject, style.get())); +} + +String WebFrame::counterValue(JSObjectRef element) +{ + if (!toJS(element)->inherits(&JSElement::s_info)) + return String(); + + return counterValueForElement(static_cast<JSElement*>(toJS(element))->impl()); +} + +String WebFrame::markerText(JSObjectRef element) +{ + if (!toJS(element)->inherits(&JSElement::s_info)) + return String(); + + return markerTextForListItem(static_cast<JSElement*>(toJS(element))->impl()); +} + +String WebFrame::provisionalURL() const +{ + if (!m_coreFrame) + return String(); + + return m_coreFrame->loader()->provisionalDocumentLoader()->url().string(); +} + +String WebFrame::suggestedFilenameForResourceWithURL(const KURL& url) const +{ + if (!m_coreFrame) + return String(); + + DocumentLoader* loader = m_coreFrame->loader()->documentLoader(); + if (!loader) + return String(); + + // First, try the main resource. + if (loader->url() == url) + return loader->response().suggestedFilename(); + + // Next, try subresources. + RefPtr<ArchiveResource> resource = loader->subresource(url); + if (resource) + return resource->response().suggestedFilename(); + + return page()->cachedSuggestedFilenameForURL(url); +} + +String WebFrame::mimeTypeForResourceWithURL(const KURL& url) const +{ + if (!m_coreFrame) + return String(); + + DocumentLoader* loader = m_coreFrame->loader()->documentLoader(); + if (!loader) + return String(); + + // First, try the main resource. + if (loader->url() == url) + return loader->response().mimeType(); + + // Next, try subresources. + RefPtr<ArchiveResource> resource = loader->subresource(url); + if (resource) + return resource->mimeType(); + + return page()->cachedResponseMIMETypeForURL(url); +} + +void WebFrame::setTextDirection(const String& direction) +{ + if (!m_coreFrame || !m_coreFrame->editor()) + return; + + if (direction == "auto") + m_coreFrame->editor()->setBaseWritingDirection(NaturalWritingDirection); + else if (direction == "ltr") + m_coreFrame->editor()->setBaseWritingDirection(LeftToRightWritingDirection); + else if (direction == "rtl") + m_coreFrame->editor()->setBaseWritingDirection(RightToLeftWritingDirection); +} + +#if PLATFORM(MAC) || PLATFORM(WIN) +RetainPtr<CFDataRef> WebFrame::webArchiveData() const +{ + if (RefPtr<LegacyWebArchive> archive = LegacyWebArchive::create(coreFrame()->document())) + return archive->rawDataRepresentation(); + + return 0; +} +#endif + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebFrame.h b/Source/WebKit2/WebProcess/WebPage/WebFrame.h new file mode 100644 index 000000000..29ced42de --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebFrame.h @@ -0,0 +1,164 @@ +/* + * 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. + */ + +#ifndef WebFrame_h +#define WebFrame_h + +#include "APIObject.h" +#include "ImmutableArray.h" +#include "WebFrameLoaderClient.h" +#include <JavaScriptCore/JSBase.h> +#include <WebCore/FrameLoaderClient.h> +#include <WebCore/FrameLoaderTypes.h> +#include <WebCore/PolicyChecker.h> +#include <wtf/Forward.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/RetainPtr.h> + +namespace WebCore { + class Frame; + class HTMLFrameOwnerElement; + class KURL; +} + +namespace WebKit { + +class InjectedBundleNodeHandle; +class InjectedBundleRangeHandle; +class InjectedBundleScriptWorld; +class WebPage; + +class WebFrame : public APIObject { +public: + static const Type APIType = TypeBundleFrame; + + static PassRefPtr<WebFrame> createMainFrame(WebPage*); + static PassRefPtr<WebFrame> createSubframe(WebPage*, const String& frameName, WebCore::HTMLFrameOwnerElement*); + ~WebFrame(); + + // Called when the FrameLoaderClient (and therefore the WebCore::Frame) is being torn down. + void invalidate(); + + WebPage* page() const; + WebCore::Frame* coreFrame() const { return m_coreFrame; } + + uint64_t frameID() const { return m_frameID; } + + uint64_t setUpPolicyListener(WebCore::FramePolicyFunction); + void invalidatePolicyListener(); + void didReceivePolicyDecision(uint64_t listenerID, WebCore::PolicyAction, uint64_t downloadID); + + void startDownload(const WebCore::ResourceRequest&); + void convertHandleToDownload(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, const WebCore::ResourceResponse&); + + String source() const; + String contentsAsString() const; + String selectionAsString() const; + + WebCore::IntSize size() const; + + // WKBundleFrame API and SPI functions + bool isMainFrame() const; + String name() const; + String url() const; + String innerText() const; + bool isFrameSet() const; + PassRefPtr<ImmutableArray> childFrames(); + JSValueRef computedStyleIncludingVisitedInfo(JSObjectRef element); + JSGlobalContextRef jsContext(); + JSGlobalContextRef jsContextForWorld(InjectedBundleScriptWorld*); + WebCore::IntRect contentBounds() const; + WebCore::IntRect visibleContentBounds() const; + WebCore::IntRect visibleContentBoundsExcludingScrollbars() const; + WebCore::IntSize scrollOffset() const; + bool hasHorizontalScrollbar() const; + bool hasVerticalScrollbar() const; + bool getDocumentBackgroundColor(double* red, double* green, double* blue, double* alpha); + bool containsAnyFormElements() const; + + static WebFrame* frameForContext(JSContextRef); + + JSValueRef jsWrapperForWorld(InjectedBundleNodeHandle*, InjectedBundleScriptWorld*); + JSValueRef jsWrapperForWorld(InjectedBundleRangeHandle*, InjectedBundleScriptWorld*); + + static String counterValue(JSObjectRef element); + static String markerText(JSObjectRef element); + + unsigned numberOfActiveAnimations() const; + bool pauseAnimationOnElementWithId(const String& animationName, const String& elementID, double time); + bool pauseTransitionOnElementWithId(const String& propertyName, const String& elementID, double time); + void suspendAnimations(); + void resumeAnimations(); + String layerTreeAsText() const; + + unsigned pendingUnloadCount() const; + + bool allowsFollowingLink(const WebCore::KURL&) const; + + String provisionalURL() const; + String suggestedFilenameForResourceWithURL(const WebCore::KURL&) const; + String mimeTypeForResourceWithURL(const WebCore::KURL&) const; + + void setTextDirection(const String&); + + // Simple listener class used by plug-ins to know when frames finish or fail loading. + class LoadListener { + public: + virtual ~LoadListener() { } + + virtual void didFinishLoad(WebFrame*) = 0; + virtual void didFailLoad(WebFrame*, bool wasCancelled) = 0; + }; + void setLoadListener(LoadListener* loadListener) { m_loadListener = loadListener; } + LoadListener* loadListener() const { return m_loadListener; } + +#if PLATFORM(MAC) || PLATFORM(WIN) + RetainPtr<CFDataRef> webArchiveData() const; +#endif + +private: + static PassRefPtr<WebFrame> create(); + WebFrame(); + + void init(WebPage*, const String& frameName, WebCore::HTMLFrameOwnerElement*); + + virtual Type type() const { return APIType; } + + WebCore::Frame* m_coreFrame; + + uint64_t m_policyListenerID; + WebCore::FramePolicyFunction m_policyFunction; + uint64_t m_policyDownloadID; + + WebFrameLoaderClient m_frameLoaderClient; + LoadListener* m_loadListener; + + uint64_t m_frameID; +}; + +} // namespace WebKit + +#endif // WebFrame_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebInspector.cpp b/Source/WebKit2/WebProcess/WebPage/WebInspector.cpp new file mode 100644 index 000000000..e1383c832 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebInspector.cpp @@ -0,0 +1,207 @@ +/* + * 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 "config.h" +#include "WebInspector.h" + +#if ENABLE(INSPECTOR) + +#include "WebInspectorFrontendClient.h" +#include "WebInspectorProxyMessages.h" +#include "WebPage.h" +#include "WebPageCreationParameters.h" +#include "WebProcess.h" +#include <WebCore/InspectorController.h> +#include <WebCore/Page.h> + +using namespace WebCore; + +namespace WebKit { + +PassRefPtr<WebInspector> WebInspector::create(WebPage* page) +{ + return adoptRef(new WebInspector(page)); +} + +WebInspector::WebInspector(WebPage* page) + : m_page(page) + , m_inspectorPage(0) + , m_frontendClient(0) +{ +} + +// Called from WebInspectorClient +WebPage* WebInspector::createInspectorPage() +{ + if (!m_page) + return 0; + + uint64_t inspectorPageID = 0; + WebPageCreationParameters parameters; + + if (!WebProcess::shared().connection()->sendSync(Messages::WebInspectorProxy::CreateInspectorPage(), + Messages::WebInspectorProxy::CreateInspectorPage::Reply(inspectorPageID, parameters), + m_page->pageID(), CoreIPC::Connection::NoTimeout)) { + return 0; + } + + if (!inspectorPageID) + return 0; + + WebProcess::shared().createWebPage(inspectorPageID, parameters); + m_inspectorPage = WebProcess::shared().webPage(inspectorPageID); + ASSERT(m_inspectorPage); + + OwnPtr<WebInspectorFrontendClient> frontendClient = adoptPtr(new WebInspectorFrontendClient(m_page, m_inspectorPage)); + m_frontendClient = frontendClient.get(); + m_inspectorPage->corePage()->inspectorController()->setInspectorFrontendClient(frontendClient.release()); + return m_inspectorPage; +} + +// Called from WebInspectorFrontendClient +void WebInspector::didLoadInspectorPage() +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::DidLoadInspectorPage(), m_page->pageID()); +} + +void WebInspector::didClose() +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::DidClose(), m_page->pageID()); +} + +void WebInspector::bringToFront() +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::BringToFront(), m_page->pageID()); +} + +void WebInspector::inspectedURLChanged(const String& urlString) +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::InspectedURLChanged(urlString), m_page->pageID()); +} + +void WebInspector::attach() +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::Attach(), m_page->pageID()); +} + +void WebInspector::detach() +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::Detach(), m_page->pageID()); +} + +void WebInspector::setAttachedWindowHeight(unsigned height) +{ + WebProcess::shared().connection()->send(Messages::WebInspectorProxy::SetAttachedWindowHeight(height), m_page->pageID()); +} + +// Called by WebInspector messages +void WebInspector::show() +{ + m_page->corePage()->inspectorController()->show(); +} + +void WebInspector::close() +{ + m_page->corePage()->inspectorController()->close(); +} + +void WebInspector::evaluateScriptForTest(long callID, const String& script) +{ + m_page->corePage()->inspectorController()->evaluateForTestInFrontend(callID, script); +} + +void WebInspector::showConsole() +{ + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->showConsole(); +} + +void WebInspector::startJavaScriptDebugging() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->setDebuggingEnabled(true); +#endif +} + +void WebInspector::stopJavaScriptDebugging() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->setDebuggingEnabled(false); +#endif +} + +void WebInspector::setJavaScriptProfilingEnabled(bool enabled) +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + m_page->corePage()->inspectorController()->show(); + if (!m_frontendClient) + return; + if (enabled) + m_page->corePage()->inspectorController()->enableProfiler(); + else + m_page->corePage()->inspectorController()->disableProfiler(); +#endif +} + +void WebInspector::startJavaScriptProfiling() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->startProfilingJavaScript(); +#endif +} + +void WebInspector::stopJavaScriptProfiling() +{ +#if ENABLE(JAVASCRIPT_DEBUGGER) + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->stopProfilingJavaScript(); +#endif +} + +void WebInspector::startPageProfiling() +{ + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->setTimelineProfilingEnabled(true); +} + +void WebInspector::stopPageProfiling() +{ + m_page->corePage()->inspectorController()->show(); + if (m_frontendClient) + m_frontendClient->setTimelineProfilingEnabled(false); +} + +} // namespace WebKit + +#endif // ENABLE(INSPECTOR) diff --git a/Source/WebKit2/WebProcess/WebPage/WebInspector.h b/Source/WebKit2/WebProcess/WebPage/WebInspector.h new file mode 100644 index 000000000..79ff8074a --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebInspector.h @@ -0,0 +1,110 @@ +/* + * 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. + */ + +#ifndef WebInspector_h +#define WebInspector_h + +#if ENABLE(INSPECTOR) + +#include "APIObject.h" +#include "Connection.h" +#include <wtf/Forward.h> +#include <wtf/Noncopyable.h> + +namespace WebKit { + +class WebInspectorFrontendClient; +class WebPage; +struct WebPageCreationParameters; + +class WebInspector : public APIObject { +public: + static const Type APIType = TypeBundleInspector; + + static PassRefPtr<WebInspector> create(WebPage*); + + WebPage* page() const { return m_page; } + WebPage* inspectorPage() const { return m_inspectorPage; } + + // Implemented in generated WebInspectorMessageReceiver.cpp + void didReceiveWebInspectorMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + + // Called by WebInspector messages + void show(); + void close(); + + void evaluateScriptForTest(long callID, const String& script); + + void setJavaScriptProfilingEnabled(bool); + void startPageProfiling(); + void stopPageProfiling(); + +#if PLATFORM(MAC) + static void setLocalizedStringsPath(const String&); +#endif + +private: + friend class WebInspectorClient; + friend class WebInspectorFrontendClient; + + explicit WebInspector(WebPage*); + + virtual Type type() const { return APIType; } + + // Called from WebInspectorClient + WebPage* createInspectorPage(); + + // Called from WebInspectorFrontendClient + void didLoadInspectorPage(); + void didClose(); + void bringToFront(); + void inspectedURLChanged(const String&); + + void attach(); + void detach(); + + void setAttachedWindowHeight(unsigned); + + // Implemented in platform WebInspector file + String localizedStringsURL() const; + + void showConsole(); + + void startJavaScriptDebugging(); + void stopJavaScriptDebugging(); + + void startJavaScriptProfiling(); + void stopJavaScriptProfiling(); + + WebPage* m_page; + WebPage* m_inspectorPage; + WebInspectorFrontendClient* m_frontendClient; +}; + +} // namespace WebKit + +#endif // ENABLE(INSPECTOR) + +#endif // WebInspector_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebInspector.messages.in b/Source/WebKit2/WebProcess/WebPage/WebInspector.messages.in new file mode 100644 index 000000000..dc184b68a --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebInspector.messages.in @@ -0,0 +1,37 @@ +# 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. + +#if ENABLE(INSPECTOR) + +messages -> WebInspector { + Show() + Close() + ShowConsole() + StartJavaScriptDebugging() + StopJavaScriptDebugging() + StartJavaScriptProfiling() + StopJavaScriptProfiling() + StartPageProfiling() + StopPageProfiling() +} + +#endif diff --git a/Source/WebKit2/WebProcess/WebPage/WebOpenPanelResultListener.cpp b/Source/WebKit2/WebProcess/WebPage/WebOpenPanelResultListener.cpp new file mode 100644 index 000000000..bcf3e8024 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebOpenPanelResultListener.cpp @@ -0,0 +1,51 @@ +/* + * 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 "config.h" +#include "WebOpenPanelResultListener.h" + +namespace WebKit { + +PassRefPtr<WebOpenPanelResultListener> WebOpenPanelResultListener::create(WebPage* page, PassRefPtr<WebCore::FileChooser> fileChooser) +{ + return adoptRef(new WebOpenPanelResultListener(page, fileChooser)); +} + +WebOpenPanelResultListener::WebOpenPanelResultListener(WebPage* page, PassRefPtr<WebCore::FileChooser> fileChooser) + : m_page(page) + , m_fileChooser(fileChooser) +{ +} + +WebOpenPanelResultListener::~WebOpenPanelResultListener() +{ +} + +void WebOpenPanelResultListener::didChooseFiles(const Vector<String>& files) +{ + m_fileChooser->chooseFiles(files); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebOpenPanelResultListener.h b/Source/WebKit2/WebProcess/WebPage/WebOpenPanelResultListener.h new file mode 100644 index 000000000..073d66adb --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebOpenPanelResultListener.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef WebOpenPanelResultListener_h +#define WebOpenPanelResultListener_h + +#include <wtf/RefCounted.h> +#include <WebCore/FileChooser.h> + +namespace WebKit { + +class WebPage; + +class WebOpenPanelResultListener : public RefCounted<WebOpenPanelResultListener> { +public: + static PassRefPtr<WebOpenPanelResultListener> create(WebPage*, PassRefPtr<WebCore::FileChooser>); + ~WebOpenPanelResultListener(); + + void disconnectFromPage() { m_page = 0; } + void didChooseFiles(const Vector<String>&); + +private: + WebOpenPanelResultListener(WebPage*, PassRefPtr<WebCore::FileChooser>); + + WebPage* m_page; + RefPtr<WebCore::FileChooser> m_fileChooser; +}; + +} // namespace WebKit + + +#endif // WebOpenPanelResultListener_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.cpp b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp new file mode 100644 index 000000000..660f6f99c --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebPage.cpp @@ -0,0 +1,2900 @@ +/* + * Copyright (C) 2010, 2011 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 "config.h" +#include "WebPage.h" + +#include "Arguments.h" +#include "DataReference.h" +#include "DecoderAdapter.h" +#include "DrawingArea.h" +#include "InjectedBundle.h" +#include "InjectedBundleBackForwardList.h" +#include "LayerTreeHost.h" +#include "MessageID.h" +#include "NetscapePlugin.h" +#include "NotificationPermissionRequestManager.h" +#include "PageOverlay.h" +#include "PluginProxy.h" +#include "PluginView.h" +#include "PrintInfo.h" +#include "RunLoop.h" +#include "SessionState.h" +#include "ShareableBitmap.h" +#include "WebBackForwardList.h" +#include "WebBackForwardListItem.h" +#include "WebBackForwardListProxy.h" +#include "WebChromeClient.h" +#include "WebContextMenu.h" +#include "WebContextMenuClient.h" +#include "WebContextMessages.h" +#include "WebCoreArgumentCoders.h" +#include "WebDragClient.h" +#include "WebEditorClient.h" +#include "WebEvent.h" +#include "WebEventConversion.h" +#include "WebFrame.h" +#include "WebFullScreenManager.h" +#include "WebGeolocationClient.h" +#include "WebGeometry.h" +#include "WebImage.h" +#include "WebInspector.h" +#include "WebInspectorClient.h" +#include "WebNotificationClient.h" +#include "WebOpenPanelResultListener.h" +#include "WebPageCreationParameters.h" +#include "WebPageGroupProxy.h" +#include "WebPageProxyMessages.h" +#include "WebPopupMenu.h" +#include "WebPreferencesStore.h" +#include "WebProcess.h" +#include "WebProcessProxyMessages.h" +#include <JavaScriptCore/APICast.h> +#include <WebCore/AbstractDatabase.h> +#include <WebCore/ArchiveResource.h> +#include <WebCore/Chrome.h> +#include <WebCore/ContextMenuController.h> +#include <WebCore/DocumentFragment.h> +#include <WebCore/DocumentLoader.h> +#include <WebCore/DocumentMarkerController.h> +#include <WebCore/DragController.h> +#include <WebCore/DragData.h> +#include <WebCore/DragSession.h> +#include <WebCore/EventHandler.h> +#include <WebCore/FocusController.h> +#include <WebCore/FormState.h> +#include <WebCore/Frame.h> +#include <WebCore/FrameLoadRequest.h> +#include <WebCore/FrameLoaderTypes.h> +#include <WebCore/FrameView.h> +#include <WebCore/HTMLFormElement.h> +#include <WebCore/HistoryItem.h> +#include <WebCore/KeyboardEvent.h> +#include <WebCore/MouseEvent.h> +#include <WebCore/Page.h> +#include <WebCore/PlatformKeyboardEvent.h> +#include <WebCore/PluginDocument.h> +#include <WebCore/PrintContext.h> +#include <WebCore/RenderArena.h> +#include <WebCore/RenderLayer.h> +#include <WebCore/RenderTreeAsText.h> +#include <WebCore/RenderView.h> +#include <WebCore/ReplaceSelectionCommand.h> +#include <WebCore/ResourceRequest.h> +#include <WebCore/SchemeRegistry.h> +#include <WebCore/ScriptValue.h> +#include <WebCore/SerializedScriptValue.h> +#include <WebCore/Settings.h> +#include <WebCore/SharedBuffer.h> +#include <WebCore/SubstituteData.h> +#include <WebCore/TextIterator.h> +#include <WebCore/markup.h> +#include <runtime/JSLock.h> +#include <runtime/JSValue.h> + +#include <WebCore/Range.h> +#include <WebCore/VisiblePosition.h> + +#if ENABLE(PLUGIN_PROCESS) +#if PLATFORM(MAC) +#include "MachPort.h" +#endif +#endif + +#if PLATFORM(MAC) +#include "BuiltInPDFView.h" +#endif + +#if PLATFORM(QT) +#include "HitTestResult.h" +#include <QMimeData> +#endif + +#if PLATFORM(GTK) +#include "DataObjectGtk.h" +#endif + +#ifndef NDEBUG +#include <wtf/RefCountedLeakCounter.h> +#endif + +using namespace JSC; +using namespace WebCore; +using namespace std; + +namespace WebKit { + +class SendStopResponsivenessTimer { +public: + SendStopResponsivenessTimer(WebPage* page) + : m_page(page) + { + } + + ~SendStopResponsivenessTimer() + { + m_page->send(Messages::WebPageProxy::StopResponsivenessTimer()); + } + +private: + WebPage* m_page; +}; + +DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, webPageCounter, ("WebPage")); + +PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters) +{ + RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters)); + + if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) + WebProcess::shared().injectedBundle()->didCreatePage(page.get()); + + return page.release(); +} + +WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters) + : m_viewSize(parameters.viewSize) + , m_useFixedLayout(false) + , m_drawsBackground(true) + , m_drawsTransparentBackground(false) + , m_isInRedo(false) + , m_isClosed(false) + , m_tabToLinks(false) +#if PLATFORM(MAC) + , m_windowIsVisible(false) + , m_isSmartInsertDeleteEnabled(parameters.isSmartInsertDeleteEnabled) + , m_keyboardEventBeingInterpreted(0) +#elif PLATFORM(WIN) + , m_nativeWindow(parameters.nativeWindow) +#endif + , m_setCanStartMediaTimer(WebProcess::shared().runLoop(), this, &WebPage::setCanStartMediaTimerFired) + , m_findController(this) + , m_geolocationPermissionRequestManager(this) + , m_pageID(pageID) + , m_canRunBeforeUnloadConfirmPanel(parameters.canRunBeforeUnloadConfirmPanel) + , m_canRunModal(parameters.canRunModal) + , m_isRunningModal(false) + , m_cachedMainFrameIsPinnedToLeftSide(false) + , m_cachedMainFrameIsPinnedToRightSide(false) + , m_cachedPageCount(0) + , m_isShowingContextMenu(false) +#if PLATFORM(WIN) + , m_gestureReachedScrollingLimit(false) +#endif +{ + ASSERT(m_pageID); + // FIXME: This is a non-ideal location for this Setting and + // 4ms should be adopted project-wide now, https://bugs.webkit.org/show_bug.cgi?id=61214 + Settings::setDefaultMinDOMTimerInterval(0.004); + + Page::PageClients pageClients; + pageClients.chromeClient = new WebChromeClient(this); + pageClients.contextMenuClient = new WebContextMenuClient(this); + pageClients.editorClient = new WebEditorClient(this); + pageClients.dragClient = new WebDragClient(this); + pageClients.backForwardClient = WebBackForwardListProxy::create(this); +#if ENABLE(CLIENT_BASED_GEOLOCATION) + pageClients.geolocationClient = new WebGeolocationClient(this); +#endif +#if ENABLE(INSPECTOR) + pageClients.inspectorClient = new WebInspectorClient(this); +#endif +#if ENABLE(NOTIFICATIONS) + pageClients.notificationClient = new WebNotificationClient(this); +#endif + + m_page = adoptPtr(new Page(pageClients)); + + // Qt does not yet call setIsInWindow. Until it does, just leave + // this line out so plug-ins and video will work. Eventually all platforms + // should call setIsInWindow and this comment and #if should be removed, + // leaving behind the setCanStartMedia call. +#if !PLATFORM(QT) + m_page->setCanStartMedia(false); +#endif + + updatePreferences(parameters.store); + + m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData); + m_page->setGroupName(m_pageGroup->identifier()); + + platformInitialize(); + + m_drawingArea = DrawingArea::create(this, parameters); + m_drawingArea->setPaintingEnabled(false); + + m_mainFrame = WebFrame::createMainFrame(this); + + setUseFixedLayout(parameters.useFixedLayout); + + setDrawsBackground(parameters.drawsBackground); + setDrawsTransparentBackground(parameters.drawsTransparentBackground); + + setPaginationMode(parameters.paginationMode); + setPageLength(parameters.pageLength); + setGapBetweenPages(parameters.gapBetweenPages); + + setMemoryCacheMessagesEnabled(parameters.areMemoryCacheClientCallsEnabled); + + setActive(parameters.isActive); + setFocused(parameters.isFocused); + setIsInWindow(parameters.isInWindow); + + m_userAgent = parameters.userAgent; + + WebBackForwardListProxy::setHighestItemIDFromUIProcess(parameters.highestUsedBackForwardItemID); + + if (!parameters.sessionState.isEmpty()) + restoreSession(parameters.sessionState); + + m_drawingArea->setPaintingEnabled(true); + +#ifndef NDEBUG + webPageCounter.increment(); +#endif +} + +WebPage::~WebPage() +{ + if (m_backForwardList) + m_backForwardList->detach(); + + ASSERT(!m_page); + + m_sandboxExtensionTracker.invalidate(); + +#if PLATFORM(MAC) + ASSERT(m_pluginViews.isEmpty()); +#endif + +#ifndef NDEBUG + webPageCounter.decrement(); +#endif +} + +void WebPage::dummy(bool&) +{ +} + +CoreIPC::Connection* WebPage::connection() const +{ + return WebProcess::shared().connection(); +} + +void WebPage::initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient* client) +{ + m_contextMenuClient.initialize(client); +} + +void WebPage::initializeInjectedBundleEditorClient(WKBundlePageEditorClient* client) +{ + m_editorClient.initialize(client); +} + +void WebPage::initializeInjectedBundleFormClient(WKBundlePageFormClient* client) +{ + m_formClient.initialize(client); +} + +void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client) +{ + m_loaderClient.initialize(client); +} + +void WebPage::initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient* client) +{ + m_policyClient.initialize(client); +} + +void WebPage::initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient* client) +{ + m_resourceLoadClient.initialize(client); +} + +void WebPage::initializeInjectedBundleUIClient(WKBundlePageUIClient* client) +{ + m_uiClient.initialize(client); +} + +#if ENABLE(FULLSCREEN_API) +void WebPage::initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient* client) +{ + m_fullScreenClient.initialize(client); +} +#endif + +PassRefPtr<Plugin> WebPage::createPlugin(WebFrame* frame, const Plugin::Parameters& parameters) +{ + String pluginPath; + + if (!WebProcess::shared().connection()->sendSync( + Messages::WebContext::GetPluginPath(parameters.mimeType, parameters.url.string()), + Messages::WebContext::GetPluginPath::Reply(pluginPath), 0)) { + return 0; + } + + if (pluginPath.isNull()) { +#if PLATFORM(MAC) + if (parameters.mimeType == "application/pdf" + || (parameters.mimeType.isEmpty() && parameters.url.path().lower().endsWith(".pdf"))) + return BuiltInPDFView::create(frame); +#else + UNUSED_PARAM(frame); +#endif + return 0; + } + +#if ENABLE(PLUGIN_PROCESS) + return PluginProxy::create(pluginPath); +#else + NetscapePlugin::setSetExceptionFunction(NPRuntimeObjectMap::setGlobalException); + return NetscapePlugin::create(NetscapePluginModule::getOrCreate(pluginPath)); +#endif +} + +EditorState WebPage::editorState() const +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + ASSERT(frame); + + EditorState result; + result.selectionIsNone = frame->selection()->isNone(); + result.selectionIsRange = frame->selection()->isRange(); + result.isContentEditable = frame->selection()->isContentEditable(); + result.isContentRichlyEditable = frame->selection()->isContentRichlyEditable(); + result.isInPasswordField = frame->selection()->isInPasswordField(); + result.hasComposition = frame->editor()->hasComposition(); + result.shouldIgnoreCompositionSelectionChange = frame->editor()->ignoreCompositionSelectionChange(); + +#if PLATFORM(QT) + size_t location = 0; + size_t length = 0; + + Element* selectionRoot = frame->selection()->rootEditableElement(); + Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement(); + + if (!scope) + return result; + + RefPtr<Range> range; + if (result.hasComposition && (range = frame->editor()->compositionRange())) { + frame->editor()->getCompositionSelection(result.anchorPosition, result.cursorPosition); + + result.compositionRect = frame->view()->contentsToWindow(range->boundingBox()); + } + + if (!result.hasComposition && !result.selectionIsNone && (range = frame->selection()->selection().firstRange())) { + TextIterator::getLocationAndLengthFromRange(scope, range.get(), location, length); + bool baseIsFirst = frame->selection()->selection().isBaseFirst(); + + result.cursorPosition = (baseIsFirst) ? location + length : location; + result.anchorPosition = (baseIsFirst) ? location : location + length; + result.selectedText = range->text(); + } + + if (range) + result.microFocus = frame->view()->contentsToWindow(frame->editor()->firstRectForRange(range.get())); + + // FIXME: We should only transfer innerText when it changes and do this on the UI side. + if (result.isContentEditable && !result.isInPasswordField) { + result.surroundingText = scope->innerText(); + if (result.hasComposition) { + // The anchor is always the left position when they represent a composition. + result.surroundingText.remove(result.anchorPosition, result.cursorPosition - result.anchorPosition); + } + } +#endif + + return result; +} + +String WebPage::renderTreeExternalRepresentation() const +{ + return externalRepresentation(m_mainFrame->coreFrame(), RenderAsTextBehaviorNormal); +} + +uint64_t WebPage::renderTreeSize() const +{ + if (!m_page) + return 0; + + Frame* mainFrame = m_page->mainFrame(); + if (!mainFrame) + return 0; + + uint64_t size = 0; + for (Frame* coreFrame = mainFrame; coreFrame; coreFrame = coreFrame->tree()->traverseNext()) + size += coreFrame->document()->renderArena()->totalRenderArenaSize(); + + return size; +} + +void WebPage::setTracksRepaints(bool trackRepaints) +{ + if (FrameView* view = mainFrameView()) + view->setTracksRepaints(trackRepaints); +} + +bool WebPage::isTrackingRepaints() const +{ + if (FrameView* view = mainFrameView()) + return view->isTrackingRepaints(); + + return false; +} + +void WebPage::resetTrackedRepaints() +{ + if (FrameView* view = mainFrameView()) + view->resetTrackedRepaints(); +} + +PassRefPtr<ImmutableArray> WebPage::trackedRepaintRects() +{ + FrameView* view = mainFrameView(); + if (!view) + return ImmutableArray::create(); + + const Vector<IntRect>& rects = view->trackedRepaintRects(); + size_t size = rects.size(); + if (!size) + return ImmutableArray::create(); + + Vector<RefPtr<APIObject> > vector; + vector.reserveInitialCapacity(size); + + for (size_t i = 0; i < size; ++i) + vector.uncheckedAppend(WebRect::create(toAPI(rects[i]))); + + return ImmutableArray::adopt(vector); +} + +void WebPage::executeEditingCommand(const String& commandName, const String& argument) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + frame->editor()->command(commandName).execute(argument); +} + +bool WebPage::isEditingCommandEnabled(const String& commandName) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return false; + + Editor::Command command = frame->editor()->command(commandName); + return command.isSupported() && command.isEnabled(); +} + +void WebPage::clearMainFrameName() +{ + if (Frame* frame = mainFrame()) + frame->tree()->clearName(); +} + +#if USE(ACCELERATED_COMPOSITING) +void WebPage::enterAcceleratedCompositingMode(GraphicsLayer* layer) +{ + m_drawingArea->setRootCompositingLayer(layer); +} + +void WebPage::exitAcceleratedCompositingMode() +{ + m_drawingArea->setRootCompositingLayer(0); +} +#endif + +void WebPage::close() +{ + if (m_isClosed) + return; + + m_isClosed = true; + + if (pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) + WebProcess::shared().injectedBundle()->willDestroyPage(this); + +#if ENABLE(INSPECTOR) + m_inspector = 0; +#endif +#if ENABLE(FULLSCREEN_API) + m_fullScreenManager = 0; +#endif + + if (m_activePopupMenu) { + m_activePopupMenu->disconnectFromPage(); + m_activePopupMenu = 0; + } + + if (m_activeOpenPanelResultListener) { + m_activeOpenPanelResultListener->disconnectFromPage(); + m_activeOpenPanelResultListener = 0; + } + + m_sandboxExtensionTracker.invalidate(); + + m_underlayPage = nullptr; + m_printContext = nullptr; + m_mainFrame->coreFrame()->loader()->detachFromParent(); + m_page = nullptr; + m_drawingArea = nullptr; + + bool isRunningModal = m_isRunningModal; + m_isRunningModal = false; + + // The WebPage can be destroyed by this call. + WebProcess::shared().removeWebPage(m_pageID); + + if (isRunningModal) + WebProcess::shared().runLoop()->stop(); +} + +void WebPage::tryClose() +{ + SendStopResponsivenessTimer stopper(this); + + if (!m_mainFrame->coreFrame()->loader()->shouldClose()) { + send(Messages::WebPageProxy::StopResponsivenessTimer()); + return; + } + + send(Messages::WebPageProxy::ClosePage(true)); +} + +void WebPage::sendClose() +{ + send(Messages::WebPageProxy::ClosePage(false)); +} + +void WebPage::loadURL(const String& url, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + loadURLRequest(ResourceRequest(KURL(KURL(), url)), sandboxExtensionHandle); +} + +void WebPage::loadURLRequest(const ResourceRequest& request, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + SendStopResponsivenessTimer stopper(this); + + m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); + m_mainFrame->coreFrame()->loader()->load(request, false); +} + +void WebPage::loadData(PassRefPtr<SharedBuffer> sharedBuffer, const String& MIMEType, const String& encodingName, const KURL& baseURL, const KURL& unreachableURL) +{ + SendStopResponsivenessTimer stopper(this); + + ResourceRequest request(baseURL); + SubstituteData substituteData(sharedBuffer, MIMEType, encodingName, unreachableURL); + m_mainFrame->coreFrame()->loader()->load(request, substituteData, false); +} + +void WebPage::loadHTMLString(const String& htmlString, const String& baseURLString) +{ + RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar)); + KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString); + loadData(sharedBuffer, "text/html", "utf-16", baseURL, KURL()); +} + +void WebPage::loadAlternateHTMLString(const String& htmlString, const String& baseURLString, const String& unreachableURLString) +{ + RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(htmlString.characters()), htmlString.length() * sizeof(UChar)); + KURL baseURL = baseURLString.isEmpty() ? blankURL() : KURL(KURL(), baseURLString); + KURL unreachableURL = unreachableURLString.isEmpty() ? KURL() : KURL(KURL(), unreachableURLString); + loadData(sharedBuffer, "text/html", "utf-16", baseURL, unreachableURL); +} + +void WebPage::loadPlainTextString(const String& string) +{ + RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(reinterpret_cast<const char*>(string.characters()), string.length() * sizeof(UChar)); + loadData(sharedBuffer, "text/plain", "utf-16", blankURL(), KURL()); +} + +void WebPage::linkClicked(const String& url, const WebMouseEvent& event) +{ + Frame* frame = m_page->mainFrame(); + if (!frame) + return; + + RefPtr<Event> coreEvent; + if (event.type() != WebEvent::NoType) + coreEvent = MouseEvent::create(eventNames().clickEvent, frame->document()->defaultView(), platform(event), 0, 0); + + frame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(url)), + false, false, coreEvent.get(), 0, MaybeSendReferrer); +} + +void WebPage::stopLoadingFrame(uint64_t frameID) +{ + WebFrame* frame = WebProcess::shared().webFrame(frameID); + if (!frame) + return; + + frame->coreFrame()->loader()->stopForUserCancel(); +} + +void WebPage::stopLoading() +{ + SendStopResponsivenessTimer stopper(this); + + m_mainFrame->coreFrame()->loader()->stopForUserCancel(); +} + +void WebPage::setDefersLoading(bool defersLoading) +{ + m_page->setDefersLoading(defersLoading); +} + +void WebPage::reload(bool reloadFromOrigin) +{ + SendStopResponsivenessTimer stopper(this); + + m_mainFrame->coreFrame()->loader()->reload(reloadFromOrigin); +} + +void WebPage::goForward(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + SendStopResponsivenessTimer stopper(this); + + HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID); + ASSERT(item); + if (!item) + return; + + m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); + m_page->goToItem(item, FrameLoadTypeForward); +} + +void WebPage::goBack(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + SendStopResponsivenessTimer stopper(this); + + HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID); + ASSERT(item); + if (!item) + return; + + m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); + m_page->goToItem(item, FrameLoadTypeBack); +} + +void WebPage::goToBackForwardItem(uint64_t backForwardItemID, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + SendStopResponsivenessTimer stopper(this); + + HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID); + ASSERT(item); + if (!item) + return; + + m_sandboxExtensionTracker.beginLoad(m_mainFrame.get(), sandboxExtensionHandle); + m_page->goToItem(item, FrameLoadTypeIndexedBackForward); +} + +void WebPage::tryRestoreScrollPosition() +{ + m_page->mainFrame()->loader()->history()->restoreScrollPositionAndViewState(); +} + +void WebPage::layoutIfNeeded() +{ + if (m_mainFrame->coreFrame()->view()) + m_mainFrame->coreFrame()->view()->updateLayoutAndStyleIfNeededRecursive(); + + if (m_underlayPage) { + if (FrameView *frameView = m_underlayPage->mainFrameView()) + frameView->updateLayoutAndStyleIfNeededRecursive(); + } +} + +void WebPage::setSize(const WebCore::IntSize& viewSize) +{ + FrameView* view = m_page->mainFrame()->view(); + +#if USE(TILED_BACKING_STORE) + // If we are resizing to content ignore external attempts. + if (view->useFixedLayout()) + return; +#endif + + if (m_viewSize == viewSize) + return; + + view->resize(viewSize); + view->setNeedsLayout(); + m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), viewSize)); + + m_viewSize = viewSize; +} + +#if USE(TILED_BACKING_STORE) +void WebPage::setFixedVisibleContentRect(const IntRect& rect) +{ + ASSERT(m_useFixedLayout); + + Frame* frame = m_page->mainFrame(); + + frame->view()->setFixedVisibleContentRect(rect); +} + +void WebPage::setResizesToContentsUsingLayoutSize(const IntSize& targetLayoutSize) +{ + ASSERT(m_useFixedLayout); + ASSERT(!targetLayoutSize.isEmpty()); + + FrameView* view = m_page->mainFrame()->view(); + + view->setDelegatesScrolling(true); + view->setUseFixedLayout(true); + view->setPaintsEntireContents(true); + + if (view->fixedLayoutSize() == targetLayoutSize) + return; + + // Always reset even when empty. + view->setFixedLayoutSize(targetLayoutSize); + + // Schedule a layout to use the new target size. + if (!view->layoutPending()) { + view->setNeedsLayout(); + view->scheduleRelayout(); + } +} + +void WebPage::resizeToContentsIfNeeded() +{ + ASSERT(m_useFixedLayout); + + FrameView* view = m_page->mainFrame()->view(); + + if (!view->useFixedLayout()) + return; + + IntSize contentSize = view->contentsSize(); + if (contentSize == m_viewSize) + return; + + m_viewSize = contentSize; + view->resize(m_viewSize); + view->setNeedsLayout(); +} + +void WebPage::setViewportSize(const IntSize& size) +{ + ASSERT(m_useFixedLayout); + + if (m_viewportSize == size) + return; + + m_viewportSize = size; + + // Recalculate the recommended layout size, when the available size (device pixel) changes. + Settings* settings = m_page->settings(); + + int minimumLayoutFallbackWidth = std::max(settings->layoutFallbackWidth(), size.width()); + + IntSize targetLayoutSize = computeViewportAttributes(m_page->viewportArguments(), minimumLayoutFallbackWidth, settings->deviceWidth(), settings->deviceHeight(), settings->deviceDPI(), size).layoutSize; + setResizesToContentsUsingLayoutSize(targetLayoutSize); +} + +#endif + +void WebPage::scrollMainFrameIfNotAtMaxScrollPosition(const IntSize& scrollOffset) +{ + Frame* frame = m_page->mainFrame(); + + IntPoint scrollPosition = frame->view()->scrollPosition(); + IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition(); + + // If the current scroll position in a direction is the max scroll position + // we don't want to scroll at all. + IntSize newScrollOffset; + if (scrollPosition.x() < maximumScrollPosition.x()) + newScrollOffset.setWidth(scrollOffset.width()); + if (scrollPosition.y() < maximumScrollPosition.y()) + newScrollOffset.setHeight(scrollOffset.height()); + + if (newScrollOffset.isZero()) + return; + + frame->view()->setScrollPosition(frame->view()->scrollPosition() + newScrollOffset); +} + +void WebPage::drawRect(GraphicsContext& graphicsContext, const IntRect& rect) +{ + GraphicsContextStateSaver stateSaver(graphicsContext); + graphicsContext.clip(rect); + + if (m_underlayPage) { + m_underlayPage->drawRect(graphicsContext, rect); + + graphicsContext.beginTransparencyLayer(1); + m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect); + graphicsContext.endTransparencyLayer(); + return; + } + + m_mainFrame->coreFrame()->view()->paint(&graphicsContext, rect); +} + +void WebPage::drawPageOverlay(GraphicsContext& graphicsContext, const IntRect& rect) +{ + ASSERT(m_pageOverlay); + + GraphicsContextStateSaver stateSaver(graphicsContext); + graphicsContext.clip(rect); + m_pageOverlay->drawRect(graphicsContext, rect); +} + +double WebPage::textZoomFactor() const +{ + Frame* frame = m_mainFrame->coreFrame(); + if (!frame) + return 1; + return frame->textZoomFactor(); +} + +void WebPage::setTextZoomFactor(double zoomFactor) +{ + Frame* frame = m_mainFrame->coreFrame(); + if (!frame) + return; + frame->setTextZoomFactor(static_cast<float>(zoomFactor)); +} + +double WebPage::pageZoomFactor() const +{ + Frame* frame = m_mainFrame->coreFrame(); + if (!frame) + return 1; + return frame->pageZoomFactor(); +} + +void WebPage::setPageZoomFactor(double zoomFactor) +{ + Frame* frame = m_mainFrame->coreFrame(); + if (!frame) + return; + frame->setPageZoomFactor(static_cast<float>(zoomFactor)); +} + +void WebPage::setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor) +{ + Frame* frame = m_mainFrame->coreFrame(); + if (!frame) + return; + return frame->setPageAndTextZoomFactors(static_cast<float>(pageZoomFactor), static_cast<float>(textZoomFactor)); +} + +void WebPage::windowScreenDidChange(uint64_t displayID) +{ + m_page->windowScreenDidChange(static_cast<PlatformDisplayID>(displayID)); +} + +void WebPage::scalePage(double scale, const IntPoint& origin) +{ + m_page->setPageScaleFactor(scale, origin); + + send(Messages::WebPageProxy::PageScaleFactorDidChange(scale)); +} + +double WebPage::pageScaleFactor() const +{ + return m_page->pageScaleFactor(); +} + +void WebPage::setDeviceScaleFactor(float scaleFactor) +{ + if (scaleFactor == m_page->deviceScaleFactor()) + return; + + m_page->setDeviceScaleFactor(scaleFactor); + + // Tell all our plug-in views that the device scale factor changed. +#if PLATFORM(MAC) + for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) + (*it)->setDeviceScaleFactor(scaleFactor); +#endif + + if (m_findController.isShowingOverlay()) { + // We must have updated layout to get the selection rects right. + layoutIfNeeded(); + m_findController.deviceScaleFactorDidChange(); + } +} + +float WebPage::deviceScaleFactor() const +{ + return m_page->deviceScaleFactor(); +} + +void WebPage::setUseFixedLayout(bool fixed) +{ + m_useFixedLayout = fixed; + + FrameView* view = mainFrameView(); + if (!view) + return; + + view->setUseFixedLayout(fixed); + if (!fixed) + view->setFixedLayoutSize(IntSize()); +} + +void WebPage::setFixedLayoutSize(const IntSize& size) +{ + FrameView* view = mainFrameView(); + if (!view) + return; + + view->setFixedLayoutSize(size); + view->forceLayout(); +} + +void WebPage::setPaginationMode(uint32_t mode) +{ + Page::Pagination pagination = m_page->pagination(); + pagination.mode = static_cast<Page::Pagination::Mode>(mode); + m_page->setPagination(pagination); +} + +void WebPage::setPageLength(double pageLength) +{ + Page::Pagination pagination = m_page->pagination(); + pagination.pageLength = pageLength; + m_page->setPagination(pagination); +} + +void WebPage::setGapBetweenPages(double gap) +{ + Page::Pagination pagination = m_page->pagination(); + pagination.gap = gap; + m_page->setPagination(pagination); +} + +void WebPage::installPageOverlay(PassRefPtr<PageOverlay> pageOverlay) +{ + bool shouldFadeIn = true; + + if (m_pageOverlay) { + m_pageOverlay->setPage(0); + + if (pageOverlay) { + // We're installing a page overlay when a page overlay is already active. + // In this case we don't want to fade in the new overlay. + shouldFadeIn = false; + } + } + + m_pageOverlay = pageOverlay; + m_pageOverlay->setPage(this); + + if (shouldFadeIn) + m_pageOverlay->startFadeInAnimation(); + + m_drawingArea->didInstallPageOverlay(); +#if PLATFORM(WIN) + send(Messages::WebPageProxy::DidInstallOrUninstallPageOverlay(true)); +#endif + + m_pageOverlay->setNeedsDisplay(); +} + +void WebPage::uninstallPageOverlay(PageOverlay* pageOverlay, bool fadeOut) +{ + if (pageOverlay != m_pageOverlay) + return; + + if (fadeOut) { + m_pageOverlay->startFadeOutAnimation(); + return; + } + + m_pageOverlay->setPage(0); + m_pageOverlay = nullptr; + + m_drawingArea->didUninstallPageOverlay(); +#if PLATFORM(WIN) + send(Messages::WebPageProxy::DidInstallOrUninstallPageOverlay(false)); +#endif +} + +PassRefPtr<WebImage> WebPage::snapshotInViewCoordinates(const IntRect& rect, ImageOptions options) +{ + FrameView* frameView = m_mainFrame->coreFrame()->view(); + if (!frameView) + return 0; + + IntSize bitmapSize = rect.size(); + float deviceScaleFactor = corePage()->deviceScaleFactor(); + bitmapSize.scale(deviceScaleFactor); + + RefPtr<WebImage> snapshot = WebImage::create(bitmapSize, options); + if (!snapshot->bitmap()) + return 0; + + OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext(); + graphicsContext->applyDeviceScaleFactor(deviceScaleFactor); + graphicsContext->translate(-rect.x(), -rect.y()); + + frameView->updateLayoutAndStyleIfNeededRecursive(); + + PaintBehavior oldBehavior = frameView->paintBehavior(); + frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers); + frameView->paint(graphicsContext.get(), rect); + frameView->setPaintBehavior(oldBehavior); + + return snapshot.release(); +} + +PassRefPtr<WebImage> WebPage::scaledSnapshotInDocumentCoordinates(const IntRect& rect, double scaleFactor, ImageOptions options) +{ + FrameView* frameView = m_mainFrame->coreFrame()->view(); + if (!frameView) + return 0; + + float combinedScaleFactor = scaleFactor * corePage()->deviceScaleFactor(); + IntSize size(ceil(rect.width() * combinedScaleFactor), ceil(rect.height() * combinedScaleFactor)); + RefPtr<WebImage> snapshot = WebImage::create(size, options); + if (!snapshot->bitmap()) + return 0; + + OwnPtr<WebCore::GraphicsContext> graphicsContext = snapshot->bitmap()->createGraphicsContext(); + graphicsContext->applyDeviceScaleFactor(combinedScaleFactor); + graphicsContext->translate(-rect.x(), -rect.y()); + + frameView->updateLayoutAndStyleIfNeededRecursive(); + + PaintBehavior oldBehavior = frameView->paintBehavior(); + frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers); + frameView->paintContents(graphicsContext.get(), rect); + frameView->setPaintBehavior(oldBehavior); + + return snapshot.release(); +} + +PassRefPtr<WebImage> WebPage::snapshotInDocumentCoordinates(const IntRect& rect, ImageOptions options) +{ + return scaledSnapshotInDocumentCoordinates(rect, 1, options); +} + +void WebPage::pageDidScroll() +{ + // Hide the find indicator. + m_findController.hideFindIndicator(); + + m_uiClient.pageDidScroll(this); + + send(Messages::WebPageProxy::PageDidScroll()); +} + +#if USE(TILED_BACKING_STORE) +void WebPage::pageDidRequestScroll(const IntPoint& point) +{ + send(Messages::WebPageProxy::PageDidRequestScroll(point)); +} +#endif + +WebContextMenu* WebPage::contextMenu() +{ + if (!m_contextMenu) + m_contextMenu = WebContextMenu::create(this); + return m_contextMenu.get(); +} + +// Events + +static const WebEvent* g_currentEvent = 0; + +// FIXME: WebPage::currentEvent is used by the plug-in code to avoid having to convert from DOM events back to +// WebEvents. When we get the event handling sorted out, this should go away and the Widgets should get the correct +// platform events passed to the event handler code. +const WebEvent* WebPage::currentEvent() +{ + return g_currentEvent; +} + +class CurrentEvent { +public: + explicit CurrentEvent(const WebEvent& event) + : m_previousCurrentEvent(g_currentEvent) + { + g_currentEvent = &event; + } + + ~CurrentEvent() + { + g_currentEvent = m_previousCurrentEvent; + } + +private: + const WebEvent* m_previousCurrentEvent; +}; + +static bool isContextClick(const PlatformMouseEvent& event) +{ + if (event.button() == WebCore::RightButton) + return true; + +#if PLATFORM(MAC) + // FIXME: this really should be about OSX-style UI, not about the Mac port + if (event.button() == WebCore::LeftButton && event.ctrlKey()) + return true; +#endif + + return false; +} + +static bool handleContextMenuEvent(const PlatformMouseEvent& platformMouseEvent, Page* page) +{ + IntPoint point = page->mainFrame()->view()->windowToContents(platformMouseEvent.position()); + HitTestResult result = page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, false); + + Frame* frame = page->mainFrame(); + if (result.innerNonSharedNode()) + frame = result.innerNonSharedNode()->document()->frame(); + + bool handled = frame->eventHandler()->sendContextMenuEvent(platformMouseEvent); + if (handled) + page->chrome()->showContextMenu(); + + return handled; +} + +static bool handleMouseEvent(const WebMouseEvent& mouseEvent, Page* page, bool onlyUpdateScrollbars) +{ + Frame* frame = page->mainFrame(); + if (!frame->view()) + return false; + + PlatformMouseEvent platformMouseEvent = platform(mouseEvent); + + switch (platformMouseEvent.type()) { + case PlatformEvent::MousePressed: { + if (isContextClick(platformMouseEvent)) + page->contextMenuController()->clearContextMenu(); + + bool handled = frame->eventHandler()->handleMousePressEvent(platformMouseEvent); + if (isContextClick(platformMouseEvent)) + handled = handleContextMenuEvent(platformMouseEvent, page); + + return handled; + } + case PlatformEvent::MouseReleased: + return frame->eventHandler()->handleMouseReleaseEvent(platformMouseEvent); + case PlatformEvent::MouseMoved: + return frame->eventHandler()->mouseMoved(platformMouseEvent, onlyUpdateScrollbars); + default: + ASSERT_NOT_REACHED(); + return false; + } +} + +void WebPage::mouseEvent(const WebMouseEvent& mouseEvent) +{ + // Don't try to handle any pending mouse events if a context menu is showing. + if (m_isShowingContextMenu) { + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), false)); + return; + } + + bool handled = false; + + if (m_pageOverlay) { + // Let the page overlay handle the event. + handled = m_pageOverlay->mouseEvent(mouseEvent); + } + + if (!handled) { + CurrentEvent currentEvent(mouseEvent); + + // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse + // button is currently pressed. It is possible that neither of those things will be true since on + // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one + // of those cases where the page is not active and the mouse is not pressed, then we can fire a more + // efficient scrollbars-only version of the event. + bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); + handled = handleMouseEvent(mouseEvent, m_page.get(), onlyUpdateScrollbars); + } + + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(mouseEvent.type()), handled)); +} + +void WebPage::mouseEventSyncForTesting(const WebMouseEvent& mouseEvent, bool& handled) +{ + // Don't try to handle any pending mouse events if a context menu is showing. + if (m_isShowingContextMenu) { + handled = true; + return; + } + + handled = m_pageOverlay && m_pageOverlay->mouseEvent(mouseEvent); + + if (!handled) { + CurrentEvent currentEvent(mouseEvent); + + // We need to do a full, normal hit test during this mouse event if the page is active or if a mouse + // button is currently pressed. It is possible that neither of those things will be true since on + // Lion when legacy scrollbars are enabled, WebKit receives mouse events all the time. If it is one + // of those cases where the page is not active and the mouse is not pressed, then we can fire a more + // efficient scrollbars-only version of the event. + bool onlyUpdateScrollbars = !(m_page->focusController()->isActive() || (mouseEvent.button() != WebMouseEvent::NoButton)); + handled = handleMouseEvent(mouseEvent, m_page.get(), onlyUpdateScrollbars); + } +} + +static bool handleWheelEvent(const WebWheelEvent& wheelEvent, Page* page) +{ + Frame* frame = page->mainFrame(); + if (!frame->view()) + return false; + + PlatformWheelEvent platformWheelEvent = platform(wheelEvent); + return frame->eventHandler()->handleWheelEvent(platformWheelEvent); +} + +void WebPage::wheelEvent(const WebWheelEvent& wheelEvent) +{ + CurrentEvent currentEvent(wheelEvent); + + bool handled = handleWheelEvent(wheelEvent, m_page.get()); + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled)); +} + +void WebPage::wheelEventSyncForTesting(const WebWheelEvent& wheelEvent, bool& handled) +{ + CurrentEvent currentEvent(wheelEvent); + + handled = handleWheelEvent(wheelEvent, m_page.get()); +} + +static bool handleKeyEvent(const WebKeyboardEvent& keyboardEvent, Page* page) +{ + if (!page->mainFrame()->view()) + return false; + + if (keyboardEvent.type() == WebEvent::Char && keyboardEvent.isSystemKey()) + return page->focusController()->focusedOrMainFrame()->eventHandler()->handleAccessKey(platform(keyboardEvent)); + return page->focusController()->focusedOrMainFrame()->eventHandler()->keyEvent(platform(keyboardEvent)); +} + +void WebPage::keyEvent(const WebKeyboardEvent& keyboardEvent) +{ + CurrentEvent currentEvent(keyboardEvent); + + bool handled = handleKeyEvent(keyboardEvent, m_page.get()); + // FIXME: Platform default behaviors should be performed during normal DOM event dispatch (in most cases, in default keydown event handler). + if (!handled) + handled = performDefaultBehaviorForKeyEvent(keyboardEvent); + + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(keyboardEvent.type()), handled)); +} + +void WebPage::keyEventSyncForTesting(const WebKeyboardEvent& keyboardEvent, bool& handled) +{ + CurrentEvent currentEvent(keyboardEvent); + + handled = handleKeyEvent(keyboardEvent, m_page.get()); + if (!handled) + handled = performDefaultBehaviorForKeyEvent(keyboardEvent); +} + +#if ENABLE(GESTURE_EVENTS) +static bool handleGestureEvent(const WebGestureEvent& gestureEvent, Page* page) +{ + Frame* frame = page->mainFrame(); + if (!frame->view()) + return false; + + PlatformGestureEvent platformGestureEvent = platform(gestureEvent); + return frame->eventHandler()->handleGestureEvent(platformGestureEvent); +} + +void WebPage::gestureEvent(const WebGestureEvent& gestureEvent) +{ + CurrentEvent currentEvent(gestureEvent); + + bool handled = handleGestureEvent(gestureEvent, m_page.get()); + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(gestureEvent.type()), handled)); +} +#endif + +void WebPage::validateCommand(const String& commandName, uint64_t callbackID) +{ + bool isEnabled = false; + int32_t state = 0; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (frame) { + Editor::Command command = frame->editor()->command(commandName); + state = command.state(); + isEnabled = command.isSupported() && command.isEnabled(); + } + + send(Messages::WebPageProxy::ValidateCommandCallback(commandName, isEnabled, state, callbackID)); +} + +void WebPage::executeEditCommand(const String& commandName) +{ + executeEditingCommand(commandName, String()); +} + +uint64_t WebPage::restoreSession(const SessionState& sessionState) +{ + const BackForwardListItemVector& list = sessionState.list(); + size_t size = list.size(); + uint64_t currentItemID = 0; + for (size_t i = 0; i < size; ++i) { + WebBackForwardListItem* webItem = list[i].get(); + DecoderAdapter decoder(webItem->backForwardData().data(), webItem->backForwardData().size()); + + RefPtr<HistoryItem> item = HistoryItem::decodeBackForwardTree(webItem->url(), webItem->title(), webItem->originalURL(), decoder); + if (!item) { + LOG_ERROR("Failed to decode a HistoryItem from session state data."); + return 0; + } + + if (i == sessionState.currentIndex()) + currentItemID = webItem->itemID(); + + WebBackForwardListProxy::addItemFromUIProcess(list[i]->itemID(), item.release()); + } + ASSERT(currentItemID); + return currentItemID; +} + +void WebPage::restoreSessionAndNavigateToCurrentItem(const SessionState& sessionState, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + if (uint64_t currentItemID = restoreSession(sessionState)) + goToBackForwardItem(currentItemID, sandboxExtensionHandle); +} + +#if ENABLE(TOUCH_EVENTS) +static bool handleTouchEvent(const WebTouchEvent& touchEvent, Page* page) +{ + Frame* frame = page->mainFrame(); + if (!frame->view()) + return false; + + return frame->eventHandler()->handleTouchEvent(platform(touchEvent)); +} + +void WebPage::touchEvent(const WebTouchEvent& touchEvent) +{ + CurrentEvent currentEvent(touchEvent); + + bool handled = handleTouchEvent(touchEvent, m_page.get()); + + send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(touchEvent.type()), handled)); +} + +void WebPage::touchEventSyncForTesting(const WebTouchEvent& touchEvent, bool& handled) +{ + CurrentEvent currentEvent(touchEvent); + handled = handleTouchEvent(touchEvent, m_page.get()); +} +#endif + +void WebPage::scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) +{ + page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity); +} + +void WebPage::logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity) +{ + page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity); +} + +void WebPage::scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity) +{ + scroll(m_page.get(), static_cast<ScrollDirection>(scrollDirection), static_cast<ScrollGranularity>(scrollGranularity)); +} + +void WebPage::centerSelectionInVisibleArea() +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + frame->selection()->revealSelection(ScrollAlignment::alignCenterAlways); + m_findController.showFindIndicatorInSelection(); +} + +void WebPage::setActive(bool isActive) +{ + m_page->focusController()->setActive(isActive); + +#if PLATFORM(MAC) + // Tell all our plug-in views that the window focus changed. + for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) + (*it)->setWindowIsFocused(isActive); +#endif +} + +void WebPage::setDrawsBackground(bool drawsBackground) +{ + if (m_drawsBackground == drawsBackground) + return; + + m_drawsBackground = drawsBackground; + + for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) { + if (FrameView* view = coreFrame->view()) + view->setTransparent(!drawsBackground); + } + + m_drawingArea->pageBackgroundTransparencyChanged(); + m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize)); +} + +void WebPage::setDrawsTransparentBackground(bool drawsTransparentBackground) +{ + if (m_drawsTransparentBackground == drawsTransparentBackground) + return; + + m_drawsTransparentBackground = drawsTransparentBackground; + + Color backgroundColor = drawsTransparentBackground ? Color::transparent : Color::white; + for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) { + if (FrameView* view = coreFrame->view()) + view->setBaseBackgroundColor(backgroundColor); + } + + m_drawingArea->pageBackgroundTransparencyChanged(); + m_drawingArea->setNeedsDisplay(IntRect(IntPoint(0, 0), m_viewSize)); +} + +void WebPage::viewWillStartLiveResize() +{ + if (!m_page) + return; + + // FIXME: This should propagate to all ScrollableAreas. + if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) { + if (FrameView* view = frame->view()) + view->willStartLiveResize(); + } +} + +void WebPage::viewWillEndLiveResize() +{ + if (!m_page) + return; + + // FIXME: This should propagate to all ScrollableAreas. + if (Frame* frame = m_page->focusController()->focusedOrMainFrame()) { + if (FrameView* view = frame->view()) + view->willEndLiveResize(); + } +} + +void WebPage::setFocused(bool isFocused) +{ + m_page->focusController()->setFocused(isFocused); +} + +void WebPage::setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent& event) +{ + if (!m_page || !m_page->focusController()) + return; + + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + frame->document()->setFocusedNode(0); + + if (isKeyboardEventValid && event.type() == WebEvent::KeyDown) { + PlatformKeyboardEvent platformEvent(platform(event)); + platformEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown); + m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, KeyboardEvent::create(platformEvent, frame->document()->defaultView()).get()); + return; + } + + m_page->focusController()->setInitialFocus(forward ? FocusDirectionForward : FocusDirectionBackward, 0); +} + +void WebPage::setWindowResizerSize(const IntSize& windowResizerSize) +{ + if (m_windowResizerSize == windowResizerSize) + return; + + m_windowResizerSize = windowResizerSize; + + for (Frame* coreFrame = m_mainFrame->coreFrame(); coreFrame; coreFrame = coreFrame->tree()->traverseNext()) { + FrameView* view = coreFrame->view(); + if (view) + view->windowResizerRectChanged(); + } +} + +void WebPage::setCanStartMediaTimerFired() +{ + if (m_page) + m_page->setCanStartMedia(true); +} + +void WebPage::setIsInWindow(bool isInWindow) +{ + if (!isInWindow) { + m_setCanStartMediaTimer.stop(); + m_page->setCanStartMedia(false); + m_page->willMoveOffscreen(); + } else { + // Defer the call to Page::setCanStartMedia() since it ends up sending a syncrhonous messages to the UI process + // in order to get plug-in connections, and the UI process will be waiting for the Web process to update the backing + // store after moving the view into a window, until it times out and paints white. See <rdar://problem/9242771>. + m_setCanStartMediaTimer.startOneShot(0); + m_page->didMoveOnscreen(); + } +} + +void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID) +{ + WebFrame* frame = WebProcess::shared().webFrame(frameID); + if (!frame) + return; + frame->didReceivePolicyDecision(listenerID, static_cast<PolicyAction>(policyAction), downloadID); +} + +void WebPage::show() +{ + send(Messages::WebPageProxy::ShowPage()); +} + +void WebPage::setUserAgent(const String& userAgent) +{ + m_userAgent = userAgent; +} + +IntPoint WebPage::screenToWindow(const IntPoint& point) +{ + IntPoint windowPoint; + sendSync(Messages::WebPageProxy::ScreenToWindow(point), Messages::WebPageProxy::ScreenToWindow::Reply(windowPoint)); + return windowPoint; +} + +IntRect WebPage::windowToScreen(const IntRect& rect) +{ + IntRect screenRect; + sendSync(Messages::WebPageProxy::WindowToScreen(rect), Messages::WebPageProxy::WindowToScreen::Reply(screenRect)); + return screenRect; +} + +IntRect WebPage::windowResizerRect() const +{ + if (m_windowResizerSize.isEmpty()) + return IntRect(); + + IntSize frameViewSize; + if (Frame* coreFrame = m_mainFrame->coreFrame()) { + if (FrameView* view = coreFrame->view()) + frameViewSize = view->size(); + } + + return IntRect(frameViewSize.width() - m_windowResizerSize.width(), frameViewSize.height() - m_windowResizerSize.height(), + m_windowResizerSize.width(), m_windowResizerSize.height()); +} + +KeyboardUIMode WebPage::keyboardUIMode() +{ + bool fullKeyboardAccessEnabled = WebProcess::shared().fullKeyboardAccessEnabled(); + return static_cast<KeyboardUIMode>((fullKeyboardAccessEnabled ? KeyboardAccessFull : KeyboardAccessDefault) | (m_tabToLinks ? KeyboardAccessTabsToLinks : 0)); +} + +void WebPage::runJavaScriptInMainFrame(const 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. + + // Retain the SerializedScriptValue at this level so it (and the internal data) lives + // long enough for the DataReference to be encoded by the sent message. + RefPtr<SerializedScriptValue> serializedResultValue; + CoreIPC::DataReference dataReference; + + JSLock lock(SilenceAssertionsOnly); + if (JSValue resultValue = m_mainFrame->coreFrame()->script()->executeScript(script, true).jsValue()) { + if ((serializedResultValue = SerializedScriptValue::create(m_mainFrame->jsContext(), toRef(m_mainFrame->coreFrame()->script()->globalObject(mainThreadNormalWorld())->globalExec(), resultValue), 0))) + dataReference = serializedResultValue->data(); + } + + send(Messages::WebPageProxy::ScriptValueCallback(dataReference, callbackID)); +} + +void WebPage::getContentsAsString(uint64_t callbackID) +{ + String resultString = m_mainFrame->contentsAsString(); + send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); +} + +void WebPage::getRenderTreeExternalRepresentation(uint64_t callbackID) +{ + String resultString = renderTreeExternalRepresentation(); + send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); +} + +void WebPage::getSelectionOrContentsAsString(uint64_t callbackID) +{ + String resultString = m_mainFrame->selectionAsString(); + if (resultString.isEmpty()) + resultString = m_mainFrame->contentsAsString(); + send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); +} + +void WebPage::getSourceForFrame(uint64_t frameID, uint64_t callbackID) +{ + String resultString; + if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) + resultString = frame->source(); + + send(Messages::WebPageProxy::StringCallback(resultString, callbackID)); +} + +void WebPage::getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID) +{ + CoreIPC::DataReference dataReference; + + RefPtr<SharedBuffer> buffer; + if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { + if (DocumentLoader* loader = frame->coreFrame()->loader()->documentLoader()) { + if ((buffer = loader->mainResourceData())) + dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); + } + } + + send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); +} + +static PassRefPtr<SharedBuffer> resourceDataForFrame(Frame* frame, const KURL& resourceURL) +{ + DocumentLoader* loader = frame->loader()->documentLoader(); + if (!loader) + return 0; + + RefPtr<ArchiveResource> subresource = loader->subresource(resourceURL); + if (!subresource) + return 0; + + return subresource->data(); +} + +void WebPage::getResourceDataFromFrame(uint64_t frameID, const String& resourceURLString, uint64_t callbackID) +{ + CoreIPC::DataReference dataReference; + KURL resourceURL(KURL(), resourceURLString); + + RefPtr<SharedBuffer> buffer; + if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { + buffer = resourceDataForFrame(frame->coreFrame(), resourceURL); + if (!buffer) { + // Try to get the resource data from the cache. + buffer = cachedResponseDataForURL(resourceURL); + } + + if (buffer) + dataReference = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(buffer->data()), buffer->size()); + } + + send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); +} + +void WebPage::getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID) +{ + CoreIPC::DataReference dataReference; + +#if PLATFORM(MAC) || PLATFORM(WIN) + RetainPtr<CFDataRef> data; + if (WebFrame* frame = WebProcess::shared().webFrame(frameID)) { + if ((data = frame->webArchiveData())) + dataReference = CoreIPC::DataReference(CFDataGetBytePtr(data.get()), CFDataGetLength(data.get())); + } +#endif + + send(Messages::WebPageProxy::DataCallback(dataReference, callbackID)); +} + +void WebPage::forceRepaintWithoutCallback() +{ + m_drawingArea->forceRepaint(); +} + +void WebPage::forceRepaint(uint64_t callbackID) +{ + forceRepaintWithoutCallback(); + send(Messages::WebPageProxy::VoidCallback(callbackID)); +} + +void WebPage::preferencesDidChange(const WebPreferencesStore& store) +{ + WebPreferencesStore::removeTestRunnerOverrides(); + updatePreferences(store); +} + +void WebPage::updatePreferences(const WebPreferencesStore& store) +{ + Settings* settings = m_page->settings(); + + m_tabToLinks = store.getBoolValueForKey(WebPreferencesKey::tabsToLinksKey()); + + // FIXME: This should be generated from macro expansion for all preferences, + // but we currently don't match the naming of WebCore exactly so we are + // handrolling the boolean and integer preferences until that is fixed. + +#define INITIALIZE_SETTINGS(KeyUpper, KeyLower, TypeName, Type, DefaultValue) settings->set##KeyUpper(store.get##TypeName##ValueForKey(WebPreferencesKey::KeyLower##Key())); + + FOR_EACH_WEBKIT_STRING_PREFERENCE(INITIALIZE_SETTINGS) + +#undef INITIALIZE_SETTINGS + + settings->setScriptEnabled(store.getBoolValueForKey(WebPreferencesKey::javaScriptEnabledKey())); + settings->setLoadsImagesAutomatically(store.getBoolValueForKey(WebPreferencesKey::loadsImagesAutomaticallyKey())); + settings->setLoadsSiteIconsIgnoringImageLoadingSetting(store.getBoolValueForKey(WebPreferencesKey::loadsSiteIconsIgnoringImageLoadingPreferenceKey())); + settings->setPluginsEnabled(store.getBoolValueForKey(WebPreferencesKey::pluginsEnabledKey())); + settings->setJavaEnabled(store.getBoolValueForKey(WebPreferencesKey::javaEnabledKey())); + settings->setOfflineWebApplicationCacheEnabled(store.getBoolValueForKey(WebPreferencesKey::offlineWebApplicationCacheEnabledKey())); + settings->setLocalStorageEnabled(store.getBoolValueForKey(WebPreferencesKey::localStorageEnabledKey())); + settings->setXSSAuditorEnabled(store.getBoolValueForKey(WebPreferencesKey::xssAuditorEnabledKey())); + settings->setFrameFlatteningEnabled(store.getBoolValueForKey(WebPreferencesKey::frameFlatteningEnabledKey())); + settings->setPrivateBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::privateBrowsingEnabledKey())); + settings->setDeveloperExtrasEnabled(store.getBoolValueForKey(WebPreferencesKey::developerExtrasEnabledKey())); + settings->setTextAreasAreResizable(store.getBoolValueForKey(WebPreferencesKey::textAreasAreResizableKey())); + settings->setNeedsSiteSpecificQuirks(store.getBoolValueForKey(WebPreferencesKey::needsSiteSpecificQuirksKey())); + settings->setJavaScriptCanOpenWindowsAutomatically(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanOpenWindowsAutomaticallyKey())); + settings->setForceFTPDirectoryListings(store.getBoolValueForKey(WebPreferencesKey::forceFTPDirectoryListingsKey())); + settings->setDNSPrefetchingEnabled(store.getBoolValueForKey(WebPreferencesKey::dnsPrefetchingEnabledKey())); +#if ENABLE(WEB_ARCHIVE) + settings->setWebArchiveDebugModeEnabled(store.getBoolValueForKey(WebPreferencesKey::webArchiveDebugModeEnabledKey())); +#endif + settings->setLocalFileContentSniffingEnabled(store.getBoolValueForKey(WebPreferencesKey::localFileContentSniffingEnabledKey())); + settings->setUsesPageCache(store.getBoolValueForKey(WebPreferencesKey::usesPageCacheKey())); + settings->setPageCacheSupportsPlugins(store.getBoolValueForKey(WebPreferencesKey::pageCacheSupportsPluginsKey())); + settings->setAuthorAndUserStylesEnabled(store.getBoolValueForKey(WebPreferencesKey::authorAndUserStylesEnabledKey())); + settings->setPaginateDuringLayoutEnabled(store.getBoolValueForKey(WebPreferencesKey::paginateDuringLayoutEnabledKey())); + settings->setDOMPasteAllowed(store.getBoolValueForKey(WebPreferencesKey::domPasteAllowedKey())); + settings->setJavaScriptCanAccessClipboard(store.getBoolValueForKey(WebPreferencesKey::javaScriptCanAccessClipboardKey())); + settings->setShouldPrintBackgrounds(store.getBoolValueForKey(WebPreferencesKey::shouldPrintBackgroundsKey())); + settings->setWebSecurityEnabled(store.getBoolValueForKey(WebPreferencesKey::webSecurityEnabledKey())); + settings->setAllowUniversalAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowUniversalAccessFromFileURLsKey())); + settings->setAllowFileAccessFromFileURLs(store.getBoolValueForKey(WebPreferencesKey::allowFileAccessFromFileURLsKey())); + + settings->setMinimumFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumFontSizeKey())); + settings->setMinimumLogicalFontSize(store.getUInt32ValueForKey(WebPreferencesKey::minimumLogicalFontSizeKey())); + settings->setDefaultFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFontSizeKey())); + settings->setDefaultFixedFontSize(store.getUInt32ValueForKey(WebPreferencesKey::defaultFixedFontSizeKey())); + settings->setLayoutFallbackWidth(store.getUInt32ValueForKey(WebPreferencesKey::layoutFallbackWidthKey())); + settings->setDeviceDPI(store.getUInt32ValueForKey(WebPreferencesKey::deviceDPIKey())); + settings->setDeviceWidth(store.getUInt32ValueForKey(WebPreferencesKey::deviceWidthKey())); + settings->setDeviceHeight(store.getUInt32ValueForKey(WebPreferencesKey::deviceHeightKey())); + settings->setEditableLinkBehavior(static_cast<WebCore::EditableLinkBehavior>(store.getUInt32ValueForKey(WebPreferencesKey::editableLinkBehaviorKey()))); + settings->setShowsToolTipOverTruncatedText(store.getBoolValueForKey(WebPreferencesKey::showsToolTipOverTruncatedTextKey())); + + settings->setAcceleratedCompositingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedCompositingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing()); + settings->setAcceleratedDrawingEnabled(store.getBoolValueForKey(WebPreferencesKey::acceleratedDrawingEnabledKey()) && LayerTreeHost::supportsAcceleratedCompositing()); + settings->setCanvasUsesAcceleratedDrawing(store.getBoolValueForKey(WebPreferencesKey::canvasUsesAcceleratedDrawingKey()) && LayerTreeHost::supportsAcceleratedCompositing()); + settings->setShowDebugBorders(store.getBoolValueForKey(WebPreferencesKey::compositingBordersVisibleKey())); + settings->setShowRepaintCounter(store.getBoolValueForKey(WebPreferencesKey::compositingRepaintCountersVisibleKey())); + settings->setWebGLEnabled(store.getBoolValueForKey(WebPreferencesKey::webGLEnabledKey())); + settings->setMediaPlaybackRequiresUserGesture(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackRequiresUserGestureKey())); + settings->setMediaPlaybackAllowsInline(store.getBoolValueForKey(WebPreferencesKey::mediaPlaybackAllowsInlineKey())); + settings->setMockScrollbarsEnabled(store.getBoolValueForKey(WebPreferencesKey::mockScrollbarsEnabledKey())); + +#if ENABLE(SQL_DATABASE) + AbstractDatabase::setIsAvailable(store.getBoolValueForKey(WebPreferencesKey::databasesEnabledKey())); +#endif + +#if ENABLE(FULLSCREEN_API) + settings->setFullScreenEnabled(store.getBoolValueForKey(WebPreferencesKey::fullScreenEnabledKey())); +#endif + + settings->setLocalStorageDatabasePath(WebProcess::shared().localStorageDirectory()); + +#if USE(AVFOUNDATION) + settings->setAVFoundationEnabled(store.getBoolValueForKey(WebPreferencesKey::isAVFoundationEnabledKey())); +#endif + +#if ENABLE(WEB_SOCKETS) + settings->setUseHixie76WebSocketProtocol(store.getBoolValueForKey(WebPreferencesKey::hixie76WebSocketProtocolEnabledKey())); +#endif + +#if ENABLE(WEB_AUDIO) + settings->setWebAudioEnabled(store.getBoolValueForKey(WebPreferencesKey::webAudioEnabledKey())); +#endif + + settings->setApplicationChromeMode(store.getBoolValueForKey(WebPreferencesKey::applicationChromeModeKey())); + settings->setSuppressIncrementalRendering(store.getBoolValueForKey(WebPreferencesKey::suppressIncrementalRenderingKey())); + settings->setBackspaceKeyNavigationEnabled(store.getBoolValueForKey(WebPreferencesKey::backspaceKeyNavigationEnabledKey())); + settings->setCaretBrowsingEnabled(store.getBoolValueForKey(WebPreferencesKey::caretBrowsingEnabledKey())); + +#if ENABLE(VIDEO_TRACK) + settings->setShouldDisplaySubtitles(store.getBoolValueForKey(WebPreferencesKey::shouldDisplaySubtitlesKey())); + settings->setShouldDisplayCaptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayCaptionsKey())); + settings->setShouldDisplayTextDescriptions(store.getBoolValueForKey(WebPreferencesKey::shouldDisplayTextDescriptionsKey())); +#endif + + platformPreferencesDidChange(store); +} + +#if ENABLE(INSPECTOR) +WebInspector* WebPage::inspector() +{ + if (m_isClosed) + return 0; + if (!m_inspector) + m_inspector = WebInspector::create(this); + return m_inspector.get(); +} +#endif + +#if ENABLE(FULLSCREEN_API) +WebFullScreenManager* WebPage::fullScreenManager() +{ + if (!m_fullScreenManager) + m_fullScreenManager = WebFullScreenManager::create(this); + return m_fullScreenManager.get(); +} +#endif + +NotificationPermissionRequestManager* WebPage::notificationPermissionRequestManager() +{ + if (m_notificationPermissionRequestManager) + return m_notificationPermissionRequestManager.get(); + + m_notificationPermissionRequestManager = NotificationPermissionRequestManager::create(this); + return m_notificationPermissionRequestManager.get(); +} + +#if !PLATFORM(GTK) && !PLATFORM(MAC) +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() == PlatformEvent::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); +} +#endif + +#if PLATFORM(WIN) +void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap& dataMap, uint32_t flags) +{ + if (!m_page) { + send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession())); + return; + } + + DragData dragData(dataMap, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags)); + switch (action) { + case DragControllerActionEntered: + send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData))); + break; + + case DragControllerActionUpdated: + send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData))); + break; + + case DragControllerActionExited: + m_page->dragController()->dragExited(&dragData); + break; + + case DragControllerActionPerformDrag: + m_page->dragController()->performDrag(&dragData); + break; + + default: + ASSERT_NOT_REACHED(); + } +} + +#elif PLATFORM(QT) || PLATFORM(GTK) +void WebPage::performDragControllerAction(uint64_t action, WebCore::DragData dragData) +{ + if (!m_page) { + send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession())); +#if PLATFORM(QT) + QMimeData* data = const_cast<QMimeData*>(dragData.platformData()); +#elif PLATFORM(GTK) + DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData()); +#endif + delete data; + return; + } + + switch (action) { + case DragControllerActionEntered: + send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData))); + break; + + case DragControllerActionUpdated: + send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData))); + break; + + case DragControllerActionExited: + m_page->dragController()->dragExited(&dragData); + break; + + case DragControllerActionPerformDrag: { + m_page->dragController()->performDrag(&dragData); + break; + } + + default: + ASSERT_NOT_REACHED(); + } + // DragData does not delete its platformData so we need to do that here. +#if PLATFORM(QT) + QMimeData* data = const_cast<QMimeData*>(dragData.platformData()); +#elif PLATFORM(GTK) + DataObjectGtk* data = const_cast<DataObjectGtk*>(dragData.platformData()); +#endif + delete data; +} + +#else +void WebPage::performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const String& dragStorageName, uint32_t flags, const SandboxExtension::Handle& sandboxExtensionHandle) +{ + if (!m_page) { + send(Messages::WebPageProxy::DidPerformDragControllerAction(WebCore::DragSession())); + return; + } + + DragData dragData(dragStorageName, clientPosition, globalPosition, static_cast<DragOperation>(draggingSourceOperationMask), static_cast<DragApplicationFlags>(flags)); + switch (action) { + case DragControllerActionEntered: + send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragEntered(&dragData))); + break; + + case DragControllerActionUpdated: + send(Messages::WebPageProxy::DidPerformDragControllerAction(m_page->dragController()->dragUpdated(&dragData))); + break; + + case DragControllerActionExited: + m_page->dragController()->dragExited(&dragData); + break; + + case DragControllerActionPerformDrag: { + ASSERT(!m_pendingDropSandboxExtension); + + m_pendingDropSandboxExtension = SandboxExtension::create(sandboxExtensionHandle); + + m_page->dragController()->performDrag(&dragData); + + // If we started loading a local file, the sandbox extension tracker would have adopted this + // pending drop sandbox extension. If not, we'll play it safe and invalidate it. + if (m_pendingDropSandboxExtension) { + m_pendingDropSandboxExtension->invalidate(); + m_pendingDropSandboxExtension = nullptr; + } + + break; + } + + default: + ASSERT_NOT_REACHED(); + } +} +#endif + +void WebPage::dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation) +{ + IntPoint adjustedClientPosition(clientPosition.x() + m_page->dragController()->dragOffset().x(), clientPosition.y() + m_page->dragController()->dragOffset().y()); + IntPoint adjustedGlobalPosition(globalPosition.x() + m_page->dragController()->dragOffset().x(), globalPosition.y() + m_page->dragController()->dragOffset().y()); + + m_page->dragController()->dragEnded(); + FrameView* view = m_page->mainFrame()->view(); + if (!view) + return; + // FIXME: These are fake modifier keys here, but they should be real ones instead. + PlatformMouseEvent event(adjustedClientPosition, adjustedGlobalPosition, LeftButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime()); + m_page->mainFrame()->eventHandler()->dragSourceEndedAt(event, (DragOperation)operation); +} + +void WebPage::willPerformLoadDragDestinationAction() +{ + m_sandboxExtensionTracker.willPerformLoadDragDestinationAction(m_pendingDropSandboxExtension.release()); +} + +WebUndoStep* WebPage::webUndoStep(uint64_t stepID) +{ + return m_undoStepMap.get(stepID).get(); +} + +void WebPage::addWebUndoStep(uint64_t stepID, WebUndoStep* entry) +{ + m_undoStepMap.set(stepID, entry); +} + +void WebPage::removeWebEditCommand(uint64_t stepID) +{ + m_undoStepMap.remove(stepID); +} + +void WebPage::unapplyEditCommand(uint64_t stepID) +{ + WebUndoStep* step = webUndoStep(stepID); + if (!step) + return; + + step->step()->unapply(); +} + +void WebPage::reapplyEditCommand(uint64_t stepID) +{ + WebUndoStep* step = webUndoStep(stepID); + if (!step) + return; + + m_isInRedo = true; + step->step()->reapply(); + m_isInRedo = false; +} + +void WebPage::didRemoveEditCommand(uint64_t commandID) +{ + removeWebEditCommand(commandID); +} + +void WebPage::setActivePopupMenu(WebPopupMenu* menu) +{ + m_activePopupMenu = menu; +} + +void WebPage::setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener> openPanelResultListener) +{ + m_activeOpenPanelResultListener = openPanelResultListener; +} + +bool WebPage::findStringFromInjectedBundle(const String& target, FindOptions options) +{ + return m_page->findString(target, options); +} + +void WebPage::findString(const String& string, uint32_t options, uint32_t maxMatchCount) +{ + m_findController.findString(string, static_cast<FindOptions>(options), maxMatchCount); +} + +void WebPage::hideFindUI() +{ + m_findController.hideFindUI(); +} + +void WebPage::countStringMatches(const String& string, uint32_t options, uint32_t maxMatchCount) +{ + m_findController.countStringMatches(string, static_cast<FindOptions>(options), maxMatchCount); +} + +void WebPage::didChangeSelectedIndexForActivePopupMenu(int32_t newIndex) +{ + if (!m_activePopupMenu) + return; + + m_activePopupMenu->didChangeSelectedIndex(newIndex); + m_activePopupMenu = 0; +} + +void WebPage::didChooseFilesForOpenPanel(const Vector<String>& files) +{ + if (!m_activeOpenPanelResultListener) + return; + + m_activeOpenPanelResultListener->didChooseFiles(files); + m_activeOpenPanelResultListener = 0; +} + +void WebPage::didCancelForOpenPanel() +{ + m_activeOpenPanelResultListener = 0; +} + +#if ENABLE(WEB_PROCESS_SANDBOX) +void WebPage::extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle& handle) +{ + SandboxExtension::create(handle)->consumePermanently(); +} +#endif + +void WebPage::didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed) +{ + m_geolocationPermissionRequestManager.didReceiveGeolocationPermissionDecision(geolocationID, allowed); +} + +void WebPage::didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed) +{ + notificationPermissionRequestManager()->didReceiveNotificationPermissionDecision(notificationID, allowed); +} + +void WebPage::advanceToNextMisspelling(bool startBeforeSelection) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + frame->editor()->advanceToNextMisspelling(startBeforeSelection); +} + +void WebPage::changeSpellingToWord(const String& word) +{ + replaceSelectionWithText(m_page->focusController()->focusedOrMainFrame(), word); +} + +void WebPage::unmarkAllMisspellings() +{ + for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + if (Document* document = frame->document()) + document->markers()->removeMarkers(DocumentMarker::Spelling); + } +} + +void WebPage::unmarkAllBadGrammar() +{ + for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) { + if (Document* document = frame->document()) + document->markers()->removeMarkers(DocumentMarker::Grammar); + } +} + +#if PLATFORM(MAC) +void WebPage::uppercaseWord() +{ + m_page->focusController()->focusedOrMainFrame()->editor()->uppercaseWord(); +} + +void WebPage::lowercaseWord() +{ + m_page->focusController()->focusedOrMainFrame()->editor()->lowercaseWord(); +} + +void WebPage::capitalizeWord() +{ + m_page->focusController()->focusedOrMainFrame()->editor()->capitalizeWord(); +} +#endif + +void WebPage::setTextForActivePopupMenu(int32_t index) +{ + if (!m_activePopupMenu) + return; + + m_activePopupMenu->setTextForIndex(index); +} + +#if PLATFORM(GTK) +void WebPage::failedToShowPopupMenu() +{ + if (!m_activePopupMenu) + return; + + m_activePopupMenu->client()->popupDidHide(); +} +#endif + +void WebPage::didSelectItemFromActiveContextMenu(const WebContextMenuItemData& item) +{ + if (!m_contextMenu) + return; + + m_contextMenu->itemSelected(item); + m_contextMenu = 0; +} + +void WebPage::replaceSelectionWithText(Frame* frame, const String& text) +{ + bool selectReplacement = true; + bool smartReplace = false; + return frame->editor()->replaceSelectionWithText(text, selectReplacement, smartReplace); +} + +void WebPage::clearSelection() +{ + m_page->focusController()->focusedOrMainFrame()->selection()->clear(); +} + +bool WebPage::mainFrameHasCustomRepresentation() const +{ + if (Frame* frame = mainFrame()) + return static_cast<WebFrameLoaderClient*>(frame->loader()->client())->frameHasCustomRepresentation(); + + return false; +} + +void WebPage::didChangeScrollOffsetForMainFrame() +{ + Frame* frame = m_page->mainFrame(); + IntPoint scrollPosition = frame->view()->scrollPosition(); + IntPoint maximumScrollPosition = frame->view()->maximumScrollPosition(); + IntPoint minimumScrollPosition = frame->view()->minimumScrollPosition(); + + bool isPinnedToLeftSide = (scrollPosition.x() <= minimumScrollPosition.x()); + bool isPinnedToRightSide = (scrollPosition.x() >= maximumScrollPosition.x()); + + if (isPinnedToLeftSide != m_cachedMainFrameIsPinnedToLeftSide || isPinnedToRightSide != m_cachedMainFrameIsPinnedToRightSide) { + send(Messages::WebPageProxy::DidChangeScrollOffsetPinningForMainFrame(isPinnedToLeftSide, isPinnedToRightSide)); + + m_cachedMainFrameIsPinnedToLeftSide = isPinnedToLeftSide; + m_cachedMainFrameIsPinnedToRightSide = isPinnedToRightSide; + } +} + +void WebPage::mainFrameDidLayout() +{ + unsigned pageCount = m_page->pageCount(); + if (pageCount != m_cachedPageCount) { + send(Messages::WebPageProxy::DidChangePageCount(pageCount)); + m_cachedPageCount = pageCount; + } +} + +#if PLATFORM(MAC) + +void WebPage::addPluginView(PluginView* pluginView) +{ + ASSERT(!m_pluginViews.contains(pluginView)); + + m_pluginViews.add(pluginView); +} + +void WebPage::removePluginView(PluginView* pluginView) +{ + ASSERT(m_pluginViews.contains(pluginView)); + + m_pluginViews.remove(pluginView); +} + +void WebPage::setWindowIsVisible(bool windowIsVisible) +{ + m_windowIsVisible = windowIsVisible; + + // Tell all our plug-in views that the window visibility changed. + for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) + (*it)->setWindowIsVisible(windowIsVisible); +} + +void WebPage::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates) +{ + m_windowFrameInScreenCoordinates = windowFrameInScreenCoordinates; + m_viewFrameInWindowCoordinates = viewFrameInWindowCoordinates; + m_accessibilityPosition = accessibilityViewCoordinates; + + // Tell all our plug-in views that the window and view frames have changed. + for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) + (*it)->windowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates); +} + +#endif + +bool WebPage::windowIsFocused() const +{ +#if PLATFORM(MAC) + if (!m_windowIsVisible) + return false; +#endif + return m_page->focusController()->isFocused() && m_page->focusController()->isActive(); +} + +void WebPage::didReceiveMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments) +{ + if (messageID.is<CoreIPC::MessageClassDrawingArea>()) { + if (m_drawingArea) + m_drawingArea->didReceiveDrawingAreaMessage(connection, messageID, arguments); + return; + } + +#if USE(TILED_BACKING_STORE) && USE(ACCELERATED_COMPOSITING) + if (messageID.is<CoreIPC::MessageClassLayerTreeHost>()) { + if (m_drawingArea) + m_drawingArea->didReceiveLayerTreeHostMessage(connection, messageID, arguments); + return; + } +#endif + +#if ENABLE(INSPECTOR) + if (messageID.is<CoreIPC::MessageClassWebInspector>()) { + if (WebInspector* inspector = this->inspector()) + inspector->didReceiveWebInspectorMessage(connection, messageID, arguments); + return; + } +#endif + +#if ENABLE(FULLSCREEN_API) + if (messageID.is<CoreIPC::MessageClassWebFullScreenManager>()) { + fullScreenManager()->didReceiveMessage(connection, messageID, arguments); + return; + } +#endif + + didReceiveWebPageMessage(connection, messageID, arguments); +} + +void WebPage::didReceiveSyncMessage(CoreIPC::Connection* connection, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments, OwnPtr<CoreIPC::ArgumentEncoder>& reply) +{ + didReceiveSyncWebPageMessage(connection, messageID, arguments, reply); +} + +InjectedBundleBackForwardList* WebPage::backForwardList() +{ + if (!m_backForwardList) + m_backForwardList = InjectedBundleBackForwardList::create(this); + return m_backForwardList.get(); +} + +#if PLATFORM(QT) +void WebPage::findZoomableAreaForPoint(const WebCore::IntPoint& point) +{ + Frame* mainframe = m_mainFrame->coreFrame(); + HitTestResult result = mainframe->eventHandler()->hitTestResultAtPoint(mainframe->view()->windowToContents(point), /*allowShadowContent*/ false, /*ignoreClipping*/ true); + + Node* node = result.innerNode(); + + if (!node) + return; + + IntRect zoomableArea = node->getRect(); + + while (true) { + bool found = !node->isTextNode() && !node->isShadowRoot(); + + // No candidate found, bail out. + if (!found && !node->parentNode()) + return; + + // Candidate found, and it is a better candidate than its parent. + // NB: A parent is considered a better candidate iff the node is + // contained by it and it is the only child. + if (found && (!node->parentNode() || node->parentNode()->childNodeCount() != 1)) + break; + + node = node->parentNode(); + zoomableArea.unite(node->getRect()); + } + + if (node->document() && node->document()->frame() && node->document()->frame()->view()) { + const ScrollView* view = node->document()->frame()->view(); + zoomableArea = view->contentsToWindow(zoomableArea); + } + + send(Messages::WebPageProxy::DidFindZoomableArea(point, zoomableArea)); +} +#endif + +WebPage::SandboxExtensionTracker::~SandboxExtensionTracker() +{ + invalidate(); +} + +void WebPage::SandboxExtensionTracker::invalidate() +{ + if (m_pendingProvisionalSandboxExtension) { + m_pendingProvisionalSandboxExtension->invalidate(); + m_pendingProvisionalSandboxExtension = 0; + } + + if (m_provisionalSandboxExtension) { + m_provisionalSandboxExtension->invalidate(); + m_provisionalSandboxExtension = 0; + } + + if (m_committedSandboxExtension) { + m_committedSandboxExtension->invalidate(); + m_committedSandboxExtension = 0; + } +} + +void WebPage::SandboxExtensionTracker::willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension) +{ + setPendingProvisionalSandboxExtension(pendingDropSandboxExtension); +} + +void WebPage::SandboxExtensionTracker::beginLoad(WebFrame* frame, const SandboxExtension::Handle& handle) +{ + ASSERT(frame->isMainFrame()); + + setPendingProvisionalSandboxExtension(SandboxExtension::create(handle)); +} + +void WebPage::SandboxExtensionTracker::setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension> pendingProvisionalSandboxExtension) +{ + // If we get two beginLoad calls in succession, without a provisional load starting, then + // m_pendingProvisionalSandboxExtension will be non-null. Invalidate and null out the extension if that is the case. + if (m_pendingProvisionalSandboxExtension) { + m_pendingProvisionalSandboxExtension->invalidate(); + m_pendingProvisionalSandboxExtension = nullptr; + } + + m_pendingProvisionalSandboxExtension = pendingProvisionalSandboxExtension; +} + +static bool shouldReuseCommittedSandboxExtension(WebFrame* frame) +{ + ASSERT(frame->isMainFrame()); + + FrameLoader* frameLoader = frame->coreFrame()->loader(); + FrameLoadType frameLoadType = frameLoader->loadType(); + + // If the page is being reloaded, it should reuse whatever extension is committed. + if (frameLoadType == FrameLoadTypeReload || frameLoadType == FrameLoadTypeReloadFromOrigin) + return true; + + DocumentLoader* documentLoader = frameLoader->documentLoader(); + DocumentLoader* provisionalDocumentLoader = frameLoader->provisionalDocumentLoader(); + if (!documentLoader || !provisionalDocumentLoader) + return false; + + if (documentLoader->url().isLocalFile() && provisionalDocumentLoader->url().isLocalFile()) + return true; + + return false; +} + +void WebPage::SandboxExtensionTracker::didStartProvisionalLoad(WebFrame* frame) +{ + if (!frame->isMainFrame()) + return; + + // We should only reuse the commited sandbox extension if it is not null. It can be + // null if the last load was for an error page. + if (m_committedSandboxExtension && shouldReuseCommittedSandboxExtension(frame)) { + m_pendingProvisionalSandboxExtension = m_committedSandboxExtension.release(); + ASSERT(!m_committedSandboxExtension); + } + + ASSERT(!m_provisionalSandboxExtension); + + m_provisionalSandboxExtension = m_pendingProvisionalSandboxExtension.release(); + if (!m_provisionalSandboxExtension) + return; + + m_provisionalSandboxExtension->consume(); +} + +void WebPage::SandboxExtensionTracker::didCommitProvisionalLoad(WebFrame* frame) +{ + if (!frame->isMainFrame()) + return; + + ASSERT(!m_pendingProvisionalSandboxExtension); + + // The provisional load has been committed. Invalidate the currently committed sandbox + // extension and make the provisional sandbox extension the committed sandbox extension. + if (m_committedSandboxExtension) + m_committedSandboxExtension->invalidate(); + + m_committedSandboxExtension = m_provisionalSandboxExtension.release(); +} + +void WebPage::SandboxExtensionTracker::didFailProvisionalLoad(WebFrame* frame) +{ + if (!frame->isMainFrame()) + return; + + if (!m_provisionalSandboxExtension) + return; + + m_provisionalSandboxExtension->invalidate(); + m_provisionalSandboxExtension = nullptr; +} + +bool WebPage::hasLocalDataForURL(const KURL& url) +{ + if (url.isLocalFile()) + return true; + + FrameLoader* frameLoader = m_page->mainFrame()->loader(); + DocumentLoader* documentLoader = frameLoader ? frameLoader->documentLoader() : 0; + if (documentLoader && documentLoader->subresource(url)) + return true; + + return platformHasLocalDataForURL(url); +} + +void WebPage::setCustomTextEncodingName(const String& encoding) +{ + m_page->mainFrame()->loader()->reloadWithOverrideEncoding(encoding); +} + +void WebPage::didRemoveBackForwardItem(uint64_t itemID) +{ + WebBackForwardListProxy::removeItem(itemID); +} + +#if PLATFORM(MAC) + +bool WebPage::isSpeaking() +{ + bool result; + return sendSync(Messages::WebPageProxy::GetIsSpeaking(), Messages::WebPageProxy::GetIsSpeaking::Reply(result)) && result; +} + +void WebPage::speak(const String& string) +{ + send(Messages::WebPageProxy::Speak(string)); +} + +void WebPage::stopSpeaking() +{ + send(Messages::WebPageProxy::StopSpeaking()); +} + +#endif + +#if USE(CG) +static RetainPtr<CGPDFDocumentRef> pdfDocumentForPrintingFrame(Frame* coreFrame) +{ + Document* document = coreFrame->document(); + if (!document) + return 0; + + if (!document->isPluginDocument()) + return 0; + + PluginView* pluginView = static_cast<PluginView*>(toPluginDocument(document)->pluginWidget()); + if (!pluginView) + return 0; + + return pluginView->pdfDocumentForPrinting(); +} +#endif // USE(CG) + +void WebPage::beginPrinting(uint64_t frameID, const PrintInfo& printInfo) +{ + WebFrame* frame = WebProcess::shared().webFrame(frameID); + if (!frame) + return; + + Frame* coreFrame = frame->coreFrame(); + if (!coreFrame) + return; + +#if USE(CG) + if (pdfDocumentForPrintingFrame(coreFrame)) + return; +#endif // USE(CG) + + if (!m_printContext) + m_printContext = adoptPtr(new PrintContext(coreFrame)); + + m_printContext->begin(printInfo.availablePaperWidth, printInfo.availablePaperHeight); + + float fullPageHeight; + m_printContext->computePageRects(FloatRect(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight), 0, 0, printInfo.pageSetupScaleFactor, fullPageHeight, true); +} + +void WebPage::endPrinting() +{ + m_printContext = nullptr; +} + +void WebPage::computePagesForPrinting(uint64_t frameID, const PrintInfo& printInfo, uint64_t callbackID) +{ + Vector<IntRect> resultPageRects; + double resultTotalScaleFactorForPrinting = 1; + + beginPrinting(frameID, printInfo); + + if (m_printContext) { + resultPageRects = m_printContext->pageRects(); + resultTotalScaleFactorForPrinting = m_printContext->computeAutomaticScaleFactor(FloatSize(printInfo.availablePaperWidth, printInfo.availablePaperHeight)) * printInfo.pageSetupScaleFactor; + } +#if USE(CG) + else { + WebFrame* frame = WebProcess::shared().webFrame(frameID); + Frame* coreFrame = frame ? frame->coreFrame() : 0; + RetainPtr<CGPDFDocumentRef> pdfDocument = coreFrame ? pdfDocumentForPrintingFrame(coreFrame) : 0; + if (pdfDocument && CGPDFDocumentAllowsPrinting(pdfDocument.get())) { + CFIndex pageCount = CGPDFDocumentGetNumberOfPages(pdfDocument.get()); + IntRect pageRect(0, 0, ceilf(printInfo.availablePaperWidth), ceilf(printInfo.availablePaperHeight)); + for (CFIndex i = 1; i <= pageCount; ++i) { + resultPageRects.append(pageRect); + pageRect.move(0, pageRect.height()); + } + } + } +#endif // USE(CG) + + // If we're asked to print, we should actually print at least a blank page. + if (resultPageRects.isEmpty()) + resultPageRects.append(IntRect(0, 0, 1, 1)); + + send(Messages::WebPageProxy::ComputedPagesCallback(resultPageRects, resultTotalScaleFactorForPrinting, callbackID)); +} + +#if USE(CG) +static inline CGFloat roundCGFloat(CGFloat f) +{ + if (sizeof(CGFloat) == sizeof(float)) + return roundf(static_cast<float>(f)); + return static_cast<CGFloat>(round(f)); +} + +static void drawPDFPage(CGPDFDocumentRef pdfDocument, CFIndex pageIndex, CGContextRef context, CGFloat pageSetupScaleFactor, CGSize paperSize) +{ + CGContextSaveGState(context); + + CGContextScaleCTM(context, pageSetupScaleFactor, pageSetupScaleFactor); + + CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, pageIndex + 1); + CGRect cropBox = CGPDFPageGetBoxRect(page, kCGPDFCropBox); + if (CGRectIsEmpty(cropBox)) + cropBox = CGRectIntersection(cropBox, CGPDFPageGetBoxRect(page, kCGPDFMediaBox)); + else + cropBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); + + bool shouldRotate = (paperSize.width < paperSize.height) != (cropBox.size.width < cropBox.size.height); + if (shouldRotate) + swap(cropBox.size.width, cropBox.size.height); + + // Center. + CGFloat widthDifference = paperSize.width / pageSetupScaleFactor - cropBox.size.width; + CGFloat heightDifference = paperSize.height / pageSetupScaleFactor - cropBox.size.height; + if (widthDifference || heightDifference) + CGContextTranslateCTM(context, roundCGFloat(widthDifference / 2), roundCGFloat(heightDifference / 2)); + + if (shouldRotate) { + CGContextRotateCTM(context, static_cast<CGFloat>(piOverTwoDouble)); + CGContextTranslateCTM(context, 0, -cropBox.size.width); + } + + CGContextDrawPDFPage(context, page); + + CGContextRestoreGState(context); +} +#endif // USE(CG) + +#if PLATFORM(MAC) || PLATFORM(WIN) +void WebPage::drawRectToPDF(uint64_t frameID, const PrintInfo& printInfo, const WebCore::IntRect& rect, uint64_t callbackID) +{ + WebFrame* frame = WebProcess::shared().webFrame(frameID); + Frame* coreFrame = frame ? frame->coreFrame() : 0; + + RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0)); + + if (coreFrame) { +#if !USE(CG) + UNUSED_PARAM(printInfo); + + ASSERT(coreFrame->document()->printing()); +#else + ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame)); + + // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data. + RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get())); + + CGRect mediaBox = CGRectMake(0, 0, rect.width(), rect.height()); + RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0)); + RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CGPDFContextBeginPage(context.get(), pageInfo.get()); + + if (RetainPtr<CGPDFDocumentRef> pdfDocument = pdfDocumentForPrintingFrame(coreFrame)) { + CFIndex pageCount = CGPDFDocumentGetNumberOfPages(pdfDocument.get()); + IntSize paperSize(ceilf(printInfo.availablePaperWidth), ceilf(printInfo.availablePaperHeight)); + IntRect pageRect(IntPoint(), paperSize); + for (CFIndex i = 0; i < pageCount; ++i) { + if (pageRect.intersects(rect)) { + CGContextSaveGState(context.get()); + + CGContextTranslateCTM(context.get(), pageRect.x() - rect.x(), pageRect.y() - rect.y()); + drawPDFPage(pdfDocument.get(), i, context.get(), printInfo.pageSetupScaleFactor, paperSize); + + CGContextRestoreGState(context.get()); + } + pageRect.move(0, pageRect.height()); + } + } else { + GraphicsContext ctx(context.get()); + ctx.scale(FloatSize(1, -1)); + ctx.translate(0, -rect.height()); + m_printContext->spoolRect(ctx, rect); + } + + CGPDFContextEndPage(context.get()); + CGPDFContextClose(context.get()); +#endif + } + + send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID)); +} + +void WebPage::drawPagesToPDF(uint64_t frameID, const PrintInfo& printInfo, uint32_t first, uint32_t count, uint64_t callbackID) +{ + WebFrame* frame = WebProcess::shared().webFrame(frameID); + Frame* coreFrame = frame ? frame->coreFrame() : 0; + + RetainPtr<CFMutableDataRef> pdfPageData(AdoptCF, CFDataCreateMutable(0, 0)); + + if (coreFrame) { + +#if !USE(CG) + ASSERT(coreFrame->document()->printing()); +#else + ASSERT(coreFrame->document()->printing() || pdfDocumentForPrintingFrame(coreFrame)); + + RetainPtr<CGPDFDocumentRef> pdfDocument = pdfDocumentForPrintingFrame(coreFrame); + + // FIXME: Use CGDataConsumerCreate with callbacks to avoid copying the data. + RetainPtr<CGDataConsumerRef> pdfDataConsumer(AdoptCF, CGDataConsumerCreateWithCFData(pdfPageData.get())); + + CGRect mediaBox = m_printContext && m_printContext->pageCount() ? m_printContext->pageRect(0) : CGRectMake(0, 0, printInfo.availablePaperWidth, printInfo.availablePaperHeight); + RetainPtr<CGContextRef> context(AdoptCF, CGPDFContextCreate(pdfDataConsumer.get(), &mediaBox, 0)); + size_t pageCount = m_printContext ? m_printContext->pageCount() : CGPDFDocumentGetNumberOfPages(pdfDocument.get()); + for (uint32_t page = first; page < first + count; ++page) { + if (page >= pageCount) + break; + + RetainPtr<CFDictionaryRef> pageInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CGPDFContextBeginPage(context.get(), pageInfo.get()); + + if (pdfDocument) + drawPDFPage(pdfDocument.get(), page, context.get(), printInfo.pageSetupScaleFactor, CGSizeMake(printInfo.availablePaperWidth, printInfo.availablePaperHeight)); + else { + GraphicsContext ctx(context.get()); + ctx.scale(FloatSize(1, -1)); + ctx.translate(0, -m_printContext->pageRect(page).height()); + m_printContext->spoolPage(ctx, page, m_printContext->pageRect(page).width()); + } + + CGPDFContextEndPage(context.get()); + } + CGPDFContextClose(context.get()); +#endif + } + + send(Messages::WebPageProxy::DataCallback(CoreIPC::DataReference(CFDataGetBytePtr(pdfPageData.get()), CFDataGetLength(pdfPageData.get())), callbackID)); +} +#endif + +void WebPage::runModal() +{ + if (m_isClosed) + return; + if (m_isRunningModal) + return; + + m_isRunningModal = true; + send(Messages::WebPageProxy::RunModal()); + RunLoop::run(); + ASSERT(!m_isRunningModal); +} + +void WebPage::setMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled) +{ + m_page->setMemoryCacheClientCallsEnabled(memoryCacheMessagesEnabled); +} + +bool WebPage::canHandleRequest(const WebCore::ResourceRequest& request) +{ + if (SchemeRegistry::shouldLoadURLSchemeAsEmptyDocument(request.url().protocol())) + return true; + return platformCanHandleRequest(request); +} + +#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) +void WebPage::handleCorrectionPanelResult(const String& result) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + frame->editor()->handleCorrectionPanelResult(result); +} +#endif + +void WebPage::simulateMouseDown(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time) +{ + mouseEvent(WebMouseEvent(WebMouseEvent::MouseDown, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time)); +} + +void WebPage::simulateMouseUp(int button, WebCore::IntPoint position, int clickCount, WKEventModifiers modifiers, double time) +{ + mouseEvent(WebMouseEvent(WebMouseEvent::MouseUp, static_cast<WebMouseEvent::Button>(button), position, position, 0, 0, 0, clickCount, static_cast<WebMouseEvent::Modifiers>(modifiers), time)); +} + +void WebPage::simulateMouseMotion(WebCore::IntPoint position, double time) +{ + mouseEvent(WebMouseEvent(WebMouseEvent::MouseMove, WebMouseEvent::NoButton, position, position, 0, 0, 0, 0, WebMouseEvent::Modifiers(), time)); +} + +String WebPage::viewportConfigurationAsText(int deviceDPI, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight) +{ + ViewportArguments arguments = mainFrame()->document()->viewportArguments(); + ViewportAttributes attrs = WebCore::computeViewportAttributes(arguments, /* default layout width for non-mobile pages */ 980, deviceWidth, deviceHeight, deviceDPI, IntSize(availableWidth, availableHeight)); + WebCore::restrictMinimumScaleFactorToViewportSize(attrs, IntSize(availableWidth, availableHeight)); + WebCore::restrictScaleFactorToInitialScaleIfNotUserScalable(attrs); + return String::format("viewport size %dx%d scale %f with limits [%f, %f] and userScalable %f\n", attrs.layoutSize.width(), attrs.layoutSize.height(), attrs.initialScale, attrs.minimumScale, attrs.maximumScale, attrs.userScalable); +} + +void WebPage::setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || !frame->editor()->canEdit()) + return; + + Vector<CompositionUnderline> underlines; + underlines.append(CompositionUnderline(0, compositionString.length(), Color(Color::black), false)); + frame->editor()->setComposition(compositionString, underlines, from, from + length); +} + +bool WebPage::hasCompositionForTesting() +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + return frame && frame->editor()->hasComposition(); +} + +void WebPage::confirmCompositionForTesting(const String& compositionString) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || !frame->editor()->canEdit()) + return; + + if (compositionString.isNull()) + frame->editor()->confirmComposition(); + frame->editor()->confirmComposition(compositionString); +} + +Frame* WebPage::mainFrame() const +{ + return m_page ? m_page->mainFrame() : 0; +} + +FrameView* WebPage::mainFrameView() const +{ + if (Frame* frame = mainFrame()) + return frame->view(); + + return 0; +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.h b/Source/WebKit2/WebProcess/WebPage/WebPage.h new file mode 100644 index 000000000..40072cfbf --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebPage.h @@ -0,0 +1,748 @@ +/* + * Copyright (C) 2010, 2011 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. + */ + +#ifndef WebPage_h +#define WebPage_h + +#include "APIObject.h" +#include "DrawingArea.h" +#include "FindController.h" +#include "GeolocationPermissionRequestManager.h" +#include "ImageOptions.h" +#include "ImmutableArray.h" +#include "InjectedBundlePageContextMenuClient.h" +#include "InjectedBundlePageEditorClient.h" +#include "InjectedBundlePageFormClient.h" +#include "InjectedBundlePageFullScreenClient.h" +#include "InjectedBundlePageLoaderClient.h" +#include "InjectedBundlePagePolicyClient.h" +#include "InjectedBundlePageResourceLoadClient.h" +#include "InjectedBundlePageUIClient.h" +#include "MessageSender.h" +#include "Plugin.h" +#include "SandboxExtension.h" +#include "ShareableBitmap.h" +#include "WebUndoStep.h" +#include <WebCore/DragData.h> +#include <WebCore/Editor.h> +#include <WebCore/FrameLoaderTypes.h> +#include <WebCore/IntRect.h> +#include <WebCore/PlatformScreen.h> +#include <WebCore/ScrollTypes.h> +#include <WebCore/WebCoreKeyboardUIMode.h> +#include <wtf/HashMap.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> +#include <wtf/text/WTFString.h> + +#if PLATFORM(QT) +#include "ArgumentCodersQt.h" +#include "QtNetworkAccessManager.h" +#include "QtNetworkReply.h" +#include "QtNetworkReplyData.h" +#include "QtNetworkRequestData.h" +#include <QNetworkReply> +#include <QNetworkRequest> +#endif + +#if PLATFORM(GTK) +#include "ArgumentCodersGtk.h" +#endif + +#if ENABLE(TOUCH_EVENTS) +#include <WebCore/PlatformTouchEvent.h> +#endif + +#if PLATFORM(MAC) +#include "DictionaryPopupInfo.h" +#include <wtf/RetainPtr.h> +OBJC_CLASS NSDictionary; +OBJC_CLASS NSObject; +OBJC_CLASS WKAccessibilityWebPageObject; +#endif + +namespace CoreIPC { + class ArgumentDecoder; + class Connection; + class MessageID; +} + +namespace WebCore { + class GraphicsContext; + class Frame; + class FrameView; + class KeyboardEvent; + class Page; + class PrintContext; + class Range; + class ResourceRequest; + class SharedBuffer; + class VisibleSelection; + struct KeypressCommand; +} + +namespace WebKit { + +class DrawingArea; +class InjectedBundleBackForwardList; +class NotificationPermissionRequestManager; +class PageOverlay; +class PluginView; +class SessionState; +class WebContextMenu; +class WebContextMenuItemData; +class WebEvent; +class WebFrame; +class WebFullScreenManager; +class WebImage; +class WebInspector; +class WebKeyboardEvent; +class WebMouseEvent; +class WebNotificationClient; +class WebOpenPanelResultListener; +class WebPageGroupProxy; +class WebPopupMenu; +class WebWheelEvent; +struct AttributedString; +struct EditorState; +struct PrintInfo; +struct WebPageCreationParameters; +struct WebPreferencesStore; + +#if ENABLE(GESTURE_EVENTS) +class WebGestureEvent; +#endif + +#if ENABLE(TOUCH_EVENTS) +class WebTouchEvent; +#endif + +class WebPage : public APIObject, public CoreIPC::MessageSender<WebPage> { +public: + static const Type APIType = TypeBundlePage; + + static PassRefPtr<WebPage> create(uint64_t pageID, const WebPageCreationParameters&); + virtual ~WebPage(); + + // Used by MessageSender. + CoreIPC::Connection* connection() const; + uint64_t destinationID() const { return pageID(); } + + void close(); + + WebCore::Page* corePage() const { return m_page.get(); } + uint64_t pageID() const { return m_pageID; } + + void setSize(const WebCore::IntSize&); + const WebCore::IntSize& size() const { return m_viewSize; } + WebCore::IntRect bounds() const { return WebCore::IntRect(WebCore::IntPoint(), size()); } + + InjectedBundleBackForwardList* backForwardList(); + DrawingArea* drawingArea() const { return m_drawingArea.get(); } + + WebPageGroupProxy* pageGroup() const { return m_pageGroup.get(); } + + void scrollMainFrameIfNotAtMaxScrollPosition(const WebCore::IntSize& scrollOffset); + + void scrollBy(uint32_t scrollDirection, uint32_t scrollGranularity); + + void centerSelectionInVisibleArea(); + +#if ENABLE(INSPECTOR) + WebInspector* inspector(); +#endif + +#if ENABLE(FULLSCREEN_API) + WebFullScreenManager* fullScreenManager(); +#endif + + // -- Called by the DrawingArea. + // FIXME: We could genericize these into a DrawingArea client interface. Would that be beneficial? + void drawRect(WebCore::GraphicsContext&, const WebCore::IntRect&); + void drawPageOverlay(WebCore::GraphicsContext&, const WebCore::IntRect&); + void layoutIfNeeded(); + + // -- Called from WebCore clients. +#if PLATFORM(MAC) + bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*, bool saveCommands); +#elif !PLATFORM(GTK) + bool handleEditingKeyboardEvent(WebCore::KeyboardEvent*); +#endif + + void show(); + String userAgent() const { return m_userAgent; } + WebCore::IntRect windowResizerRect() const; + WebCore::KeyboardUIMode keyboardUIMode(); + + WebUndoStep* webUndoStep(uint64_t); + void addWebUndoStep(uint64_t, WebUndoStep*); + void removeWebEditCommand(uint64_t); + bool isInRedo() const { return m_isInRedo; } + + void setActivePopupMenu(WebPopupMenu*); + + WebOpenPanelResultListener* activeOpenPanelResultListener() const { return m_activeOpenPanelResultListener.get(); } + void setActiveOpenPanelResultListener(PassRefPtr<WebOpenPanelResultListener>); + + // -- Called from WebProcess. + void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + void didReceiveSyncMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&); + + // -- InjectedBundle methods + void initializeInjectedBundleContextMenuClient(WKBundlePageContextMenuClient*); + void initializeInjectedBundleEditorClient(WKBundlePageEditorClient*); + void initializeInjectedBundleFormClient(WKBundlePageFormClient*); + void initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient*); + void initializeInjectedBundlePolicyClient(WKBundlePagePolicyClient*); + void initializeInjectedBundleResourceLoadClient(WKBundlePageResourceLoadClient*); + void initializeInjectedBundleUIClient(WKBundlePageUIClient*); +#if ENABLE(FULLSCREEN_API) + void initializeInjectedBundleFullScreenClient(WKBundlePageFullScreenClient*); +#endif + + InjectedBundlePageContextMenuClient& injectedBundleContextMenuClient() { return m_contextMenuClient; } + InjectedBundlePageEditorClient& injectedBundleEditorClient() { return m_editorClient; } + InjectedBundlePageFormClient& injectedBundleFormClient() { return m_formClient; } + InjectedBundlePageLoaderClient& injectedBundleLoaderClient() { return m_loaderClient; } + InjectedBundlePagePolicyClient& injectedBundlePolicyClient() { return m_policyClient; } + InjectedBundlePageResourceLoadClient& injectedBundleResourceLoadClient() { return m_resourceLoadClient; } + InjectedBundlePageUIClient& injectedBundleUIClient() { return m_uiClient; } +#if ENABLE(FULLSCREEN_API) + InjectedBundlePageFullScreenClient& injectedBundleFullScreenClient() { return m_fullScreenClient; } +#endif + + void setUnderlayPage(PassRefPtr<WebPage> underlayPage) { m_underlayPage = underlayPage; } + + bool findStringFromInjectedBundle(const String&, FindOptions); + + WebFrame* mainWebFrame() const { return m_mainFrame.get(); } + + WebCore::Frame* mainFrame() const; // May return 0. + WebCore::FrameView* mainFrameView() const; // May return 0. + + PassRefPtr<Plugin> createPlugin(WebFrame*, const Plugin::Parameters&); + + EditorState editorState() const; + + String renderTreeExternalRepresentation() const; + uint64_t renderTreeSize() const; + + void setTracksRepaints(bool); + bool isTrackingRepaints() const; + void resetTrackedRepaints(); + PassRefPtr<ImmutableArray> trackedRepaintRects(); + + void executeEditingCommand(const String& commandName, const String& argument); + bool isEditingCommandEnabled(const String& commandName); + void clearMainFrameName(); + void sendClose(); + + double textZoomFactor() const; + void setTextZoomFactor(double); + double pageZoomFactor() const; + void setPageZoomFactor(double); + void setPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor); + void windowScreenDidChange(uint64_t); + + void scalePage(double scale, const WebCore::IntPoint& origin); + double pageScaleFactor() const; + + void setUseFixedLayout(bool); + bool useFixedLayout() const { return m_useFixedLayout; } + void setFixedLayoutSize(const WebCore::IntSize&); + + void setPaginationMode(uint32_t /* WebCore::Page::Pagination::Mode */); + void setPageLength(double); + void setGapBetweenPages(double); + + bool drawsBackground() const { return m_drawsBackground; } + bool drawsTransparentBackground() const { return m_drawsTransparentBackground; } + + void stopLoading(); + void stopLoadingFrame(uint64_t frameID); + void setDefersLoading(bool deferLoading); + +#if USE(ACCELERATED_COMPOSITING) + void enterAcceleratedCompositingMode(WebCore::GraphicsLayer*); + void exitAcceleratedCompositingMode(); +#endif + +#if PLATFORM(MAC) + void addPluginView(PluginView*); + void removePluginView(PluginView*); + + bool windowIsVisible() const { return m_windowIsVisible; } + const WebCore::IntRect& windowFrameInScreenCoordinates() const { return m_windowFrameInScreenCoordinates; } + const WebCore::IntRect& viewFrameInWindowCoordinates() const { return m_viewFrameInWindowCoordinates; } +#elif PLATFORM(WIN) + HWND nativeWindow() const { return m_nativeWindow; } +#endif + + bool windowIsFocused() const; + void installPageOverlay(PassRefPtr<PageOverlay>); + void uninstallPageOverlay(PageOverlay*, bool fadeOut); + bool hasPageOverlay() const { return m_pageOverlay; } + WebCore::IntPoint screenToWindow(const WebCore::IntPoint&); + WebCore::IntRect windowToScreen(const WebCore::IntRect&); + + PassRefPtr<WebImage> snapshotInViewCoordinates(const WebCore::IntRect&, ImageOptions); + PassRefPtr<WebImage> snapshotInDocumentCoordinates(const WebCore::IntRect&, ImageOptions); + PassRefPtr<WebImage> scaledSnapshotInDocumentCoordinates(const WebCore::IntRect&, double scaleFactor, ImageOptions); + + static const WebEvent* currentEvent(); + + FindController& findController() { return m_findController; } + GeolocationPermissionRequestManager& geolocationPermissionRequestManager() { return m_geolocationPermissionRequestManager; } + NotificationPermissionRequestManager* notificationPermissionRequestManager(); + + void pageDidScroll(); +#if USE(TILED_BACKING_STORE) + void pageDidRequestScroll(const WebCore::IntPoint&); + void setFixedVisibleContentRect(const WebCore::IntRect&); + void setResizesToContentsUsingLayoutSize(const WebCore::IntSize&); + void resizeToContentsIfNeeded(); + void setViewportSize(const WebCore::IntSize&); + WebCore::IntSize viewportSize() const { return m_viewportSize; } +#endif + + WebContextMenu* contextMenu(); + + bool hasLocalDataForURL(const WebCore::KURL&); + String cachedResponseMIMETypeForURL(const WebCore::KURL&); + String cachedSuggestedFilenameForURL(const WebCore::KURL&); + PassRefPtr<WebCore::SharedBuffer> cachedResponseDataForURL(const WebCore::KURL&); + + static bool canHandleRequest(const WebCore::ResourceRequest&); + + class SandboxExtensionTracker { + public: + ~SandboxExtensionTracker(); + + void invalidate(); + + void beginLoad(WebFrame*, const SandboxExtension::Handle& handle); + void willPerformLoadDragDestinationAction(PassRefPtr<SandboxExtension> pendingDropSandboxExtension); + void didStartProvisionalLoad(WebFrame*); + void didCommitProvisionalLoad(WebFrame*); + void didFailProvisionalLoad(WebFrame*); + + private: + void setPendingProvisionalSandboxExtension(PassRefPtr<SandboxExtension>); + + RefPtr<SandboxExtension> m_pendingProvisionalSandboxExtension; + RefPtr<SandboxExtension> m_provisionalSandboxExtension; + RefPtr<SandboxExtension> m_committedSandboxExtension; + }; + + SandboxExtensionTracker& sandboxExtensionTracker() { return m_sandboxExtensionTracker; } + +#if PLATFORM(QT) + void setComposition(const String& text, Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd); + void confirmComposition(const String& text, int64_t selectionStart, int64_t selectionLength); + void cancelComposition(); +#endif + +#if PLATFORM(MAC) + void registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elemenToken, const CoreIPC::DataReference& windowToken); + WKAccessibilityWebPageObject* accessibilityRemoteObject(); + WebCore::IntPoint accessibilityPosition() const { return m_accessibilityPosition; } + + void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput); + + void setComposition(const String& text, Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, EditorState& newState); + void confirmComposition(EditorState& newState); + void cancelComposition(EditorState& newState); + void insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, bool& handled, EditorState& newState); + void getMarkedRange(uint64_t& location, uint64_t& length); + void getSelectedRange(uint64_t& location, uint64_t& length); + void getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString&); + void characterIndexForPoint(const WebCore::IntPoint point, uint64_t& result); + void firstRectForCharacterRange(uint64_t location, uint64_t length, WebCore::IntRect& resultRect); + void executeKeypressCommands(const Vector<WebCore::KeypressCommand>&, bool& handled, EditorState& newState); + void writeSelectionToPasteboard(const WTF::String& pasteboardName, const WTF::Vector<WTF::String>& pasteboardTypes, bool& result); + void readSelectionFromPasteboard(const WTF::String& pasteboardName, bool& result); + void shouldDelayWindowOrderingEvent(const WebKit::WebMouseEvent&, bool& result); + void acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent&, bool& result); + bool performNonEditingBehaviorForSelector(const String&); + +#elif PLATFORM(WIN) + void confirmComposition(const String& compositionString); + void setComposition(const WTF::String& compositionString, const WTF::Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition); + void firstRectForCharacterInSelectedRange(const uint64_t characterPosition, WebCore::IntRect& resultRect); + void getSelectedText(WTF::String&); + + void gestureWillBegin(const WebCore::IntPoint&, bool& canBeginPanning); + void gestureDidScroll(const WebCore::IntSize&); + void gestureDidEnd(); +#endif + + void setCompositionForTesting(const String& compositionString, uint64_t from, uint64_t length); + bool hasCompositionForTesting(); + void confirmCompositionForTesting(const String& compositionString); + + // FIXME: This a dummy message, to avoid breaking the build for platforms that don't require + // any synchronous messages, and should be removed when <rdar://problem/8775115> is fixed. + void dummy(bool&); + +#if PLATFORM(MAC) + void performDictionaryLookupForSelection(DictionaryPopupInfo::Type, WebCore::Frame*, const WebCore::VisibleSelection&); + + bool isSpeaking(); + void speak(const String&); + void stopSpeaking(); + + bool isSmartInsertDeleteEnabled() const { return m_isSmartInsertDeleteEnabled; } +#endif + + void replaceSelectionWithText(WebCore::Frame*, const String&); + void clearSelection(); +#if PLATFORM(WIN) + void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WebCore::DragDataMap&, uint32_t flags); +#elif PLATFORM(QT) || PLATFORM(GTK) + void performDragControllerAction(uint64_t action, WebCore::DragData); +#else + void performDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, const WTF::String& dragStorageName, uint32_t flags, const SandboxExtension::Handle&); +#endif + void dragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation); + + void willPerformLoadDragDestinationAction(); + + void beginPrinting(uint64_t frameID, const PrintInfo&); + void endPrinting(); + void computePagesForPrinting(uint64_t frameID, const PrintInfo&, uint64_t callbackID); +#if PLATFORM(MAC) || PLATFORM(WIN) + void drawRectToPDF(uint64_t frameID, const PrintInfo&, const WebCore::IntRect&, uint64_t callbackID); + void drawPagesToPDF(uint64_t frameID, const PrintInfo&, uint32_t first, uint32_t count, uint64_t callbackID); +#endif + + bool mainFrameHasCustomRepresentation() const; + + void didChangeScrollOffsetForMainFrame(); + + void mainFrameDidLayout(); + + bool canRunBeforeUnloadConfirmPanel() const { return m_canRunBeforeUnloadConfirmPanel; } + void setCanRunBeforeUnloadConfirmPanel(bool canRunBeforeUnloadConfirmPanel) { m_canRunBeforeUnloadConfirmPanel = canRunBeforeUnloadConfirmPanel; } + + bool canRunModal() const { return m_canRunModal; } + void setCanRunModal(bool canRunModal) { m_canRunModal = canRunModal; } + + void runModal(); + + void setDeviceScaleFactor(float); + float deviceScaleFactor() const; + + void setMemoryCacheMessagesEnabled(bool); + + void forceRepaintWithoutCallback(); + + void unmarkAllMisspellings(); + void unmarkAllBadGrammar(); + +#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) + void handleCorrectionPanelResult(const String&); +#endif + + // For testing purpose. + void simulateMouseDown(int button, WebCore::IntPoint, int clickCount, WKEventModifiers, double time); + void simulateMouseUp(int button, WebCore::IntPoint, int clickCount, WKEventModifiers, double time); + void simulateMouseMotion(WebCore::IntPoint, double time); + String viewportConfigurationAsText(int deviceDPI, int deviceWidth, int deviceHeight, int availableWidth, int availableHeight); + + void contextMenuShowing() { m_isShowingContextMenu = true; } + +#if PLATFORM(QT) + void registerApplicationScheme(const String& scheme); + void applicationSchemeReply(const QtNetworkReplyData&); + void receivedApplicationSchemeRequest(const QNetworkRequest&, QtNetworkReply*); +#endif + void wheelEvent(const WebWheelEvent&); +#if ENABLE(GESTURE_EVENTS) + void gestureEvent(const WebGestureEvent&); +#endif + +private: + WebPage(uint64_t pageID, const WebPageCreationParameters&); + + virtual Type type() const { return APIType; } + + void platformInitialize(); + + void didReceiveWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*); + void didReceiveSyncWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*, OwnPtr<CoreIPC::ArgumentEncoder>&); + +#if !PLATFORM(MAC) + static const char* interpretKeyEvent(const WebCore::KeyboardEvent*); +#endif + bool performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&); + +#if PLATFORM(MAC) + bool executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>&, WebCore::KeyboardEvent*); +#endif + + String sourceForFrame(WebFrame*); + + void loadData(PassRefPtr<WebCore::SharedBuffer>, const String& MIMEType, const String& encodingName, const WebCore::KURL& baseURL, const WebCore::KURL& failingURL); + + bool platformHasLocalDataForURL(const WebCore::KURL&); + + // Actions + void tryClose(); + void loadURL(const String&, const SandboxExtension::Handle&); + void loadURLRequest(const WebCore::ResourceRequest&, const SandboxExtension::Handle&); + void loadHTMLString(const String& htmlString, const String& baseURL); + void loadAlternateHTMLString(const String& htmlString, const String& baseURL, const String& unreachableURL); + void loadPlainTextString(const String&); + void linkClicked(const String& url, const WebMouseEvent&); + void reload(bool reloadFromOrigin); + void goForward(uint64_t, const SandboxExtension::Handle&); + void goBack(uint64_t, const SandboxExtension::Handle&); + void goToBackForwardItem(uint64_t, const SandboxExtension::Handle&); + void tryRestoreScrollPosition(); + void setActive(bool); + void setFocused(bool); + void setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent&); + void setWindowResizerSize(const WebCore::IntSize&); + void setIsInWindow(bool); + void validateCommand(const String&, uint64_t); + void executeEditCommand(const String&); + + void mouseEvent(const WebMouseEvent&); + void mouseEventSyncForTesting(const WebMouseEvent&, bool&); + void wheelEventSyncForTesting(const WebWheelEvent&, bool&); + void keyEvent(const WebKeyboardEvent&); + void keyEventSyncForTesting(const WebKeyboardEvent&, bool&); +#if ENABLE(TOUCH_EVENTS) + void touchEvent(const WebTouchEvent&); + void touchEventSyncForTesting(const WebTouchEvent&, bool& handled); +#endif + void contextMenuHidden() { m_isShowingContextMenu = false; } + + static void scroll(WebCore::Page*, WebCore::ScrollDirection, WebCore::ScrollGranularity); + static void logicalScroll(WebCore::Page*, WebCore::ScrollLogicalDirection, WebCore::ScrollGranularity); + + uint64_t restoreSession(const SessionState&); + void restoreSessionAndNavigateToCurrentItem(const SessionState&, const SandboxExtension::Handle&); + + void didRemoveBackForwardItem(uint64_t); + + void setDrawsBackground(bool); + void setDrawsTransparentBackground(bool); + + void viewWillStartLiveResize(); + void viewWillEndLiveResize(); + + void getContentsAsString(uint64_t callbackID); + void getMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID); + void getResourceDataFromFrame(uint64_t frameID, const String& resourceURL, uint64_t callbackID); + void getRenderTreeExternalRepresentation(uint64_t callbackID); + void getSelectionOrContentsAsString(uint64_t callbackID); + void getSourceForFrame(uint64_t frameID, uint64_t callbackID); + void getWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID); + void runJavaScriptInMainFrame(const String&, uint64_t callbackID); + void forceRepaint(uint64_t callbackID); + + void preferencesDidChange(const WebPreferencesStore&); + void platformPreferencesDidChange(const WebPreferencesStore&); + void updatePreferences(const WebPreferencesStore&); + + void didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID); + void setUserAgent(const String&); + void setCustomTextEncodingName(const String&); + +#if PLATFORM(MAC) + void performDictionaryLookupAtLocation(const WebCore::FloatPoint&); + void performDictionaryLookupForRange(DictionaryPopupInfo::Type, WebCore::Frame*, WebCore::Range*, NSDictionary *options); + + void setWindowIsVisible(bool windowIsVisible); + void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates, const WebCore::IntPoint& accessibilityViewCoordinates); +#endif + + void unapplyEditCommand(uint64_t commandID); + void reapplyEditCommand(uint64_t commandID); + void didRemoveEditCommand(uint64_t commandID); + + void findString(const String&, uint32_t findOptions, uint32_t maxMatchCount); + void hideFindUI(); + void countStringMatches(const String&, uint32_t findOptions, uint32_t maxMatchCount); + +#if PLATFORM(QT) + void findZoomableAreaForPoint(const WebCore::IntPoint&); +#endif + + void didChangeSelectedIndexForActivePopupMenu(int32_t newIndex); + void setTextForActivePopupMenu(int32_t index); + +#if PLATFORM(GTK) + void failedToShowPopupMenu(); +#endif + + void didChooseFilesForOpenPanel(const Vector<String>&); + void didCancelForOpenPanel(); +#if ENABLE(WEB_PROCESS_SANDBOX) + void extendSandboxForFileFromOpenPanel(const SandboxExtension::Handle&); +#endif + + void didReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed); + void didReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed); + + void advanceToNextMisspelling(bool startBeforeSelection); + void changeSpellingToWord(const String& word); +#if PLATFORM(MAC) + void uppercaseWord(); + void lowercaseWord(); + void capitalizeWord(); + + void setSmartInsertDeleteEnabled(bool isSmartInsertDeleteEnabled) { m_isSmartInsertDeleteEnabled = isSmartInsertDeleteEnabled; } +#endif + +#if ENABLE(CONTEXT_MENUS) + void didSelectItemFromActiveContextMenu(const WebContextMenuItemData&); +#endif + + void setCanStartMediaTimerFired(); + + static bool platformCanHandleRequest(const WebCore::ResourceRequest&); + + OwnPtr<WebCore::Page> m_page; + RefPtr<WebFrame> m_mainFrame; + RefPtr<InjectedBundleBackForwardList> m_backForwardList; + + RefPtr<WebPageGroupProxy> m_pageGroup; + + String m_userAgent; + + WebCore::IntSize m_viewSize; + OwnPtr<DrawingArea> m_drawingArea; + bool m_useFixedLayout; + + bool m_drawsBackground; + bool m_drawsTransparentBackground; + + bool m_isInRedo; + bool m_isClosed; + + bool m_tabToLinks; + +#if PLATFORM(MAC) + // Whether the containing window is visible or not. + bool m_windowIsVisible; + + // Whether smart insert/delete is enabled or not. + bool m_isSmartInsertDeleteEnabled; + + // The frame of the containing window in screen coordinates. + WebCore::IntRect m_windowFrameInScreenCoordinates; + + // The frame of the view in window coordinates. + WebCore::IntRect m_viewFrameInWindowCoordinates; + + // The accessibility position of the view. + WebCore::IntPoint m_accessibilityPosition; + + // All plug-in views on this web page. + HashSet<PluginView*> m_pluginViews; + + RetainPtr<WKAccessibilityWebPageObject> m_mockAccessibilityElement; + + WebCore::KeyboardEvent* m_keyboardEventBeingInterpreted; + +#elif PLATFORM(WIN) + // Our view's window (in the UI process). + HWND m_nativeWindow; + + RefPtr<WebCore::Node> m_gestureTargetNode; +#endif + + RunLoop::Timer<WebPage> m_setCanStartMediaTimer; + + HashMap<uint64_t, RefPtr<WebUndoStep> > m_undoStepMap; + + WebCore::IntSize m_windowResizerSize; + + InjectedBundlePageContextMenuClient m_contextMenuClient; + InjectedBundlePageEditorClient m_editorClient; + InjectedBundlePageFormClient m_formClient; + InjectedBundlePageLoaderClient m_loaderClient; + InjectedBundlePagePolicyClient m_policyClient; + InjectedBundlePageResourceLoadClient m_resourceLoadClient; + InjectedBundlePageUIClient m_uiClient; +#if ENABLE(FULLSCREEN_API) + InjectedBundlePageFullScreenClient m_fullScreenClient; +#endif + +#if USE(TILED_BACKING_STORE) + WebCore::IntSize m_resizesToContentsLayoutSize; + WebCore::IntSize m_viewportSize; +#endif + + FindController m_findController; + RefPtr<PageOverlay> m_pageOverlay; + + RefPtr<WebPage> m_underlayPage; + +#if ENABLE(INSPECTOR) + RefPtr<WebInspector> m_inspector; +#endif +#if ENABLE(FULLSCREEN_API) + RefPtr<WebFullScreenManager> m_fullScreenManager; +#endif + RefPtr<WebPopupMenu> m_activePopupMenu; + RefPtr<WebContextMenu> m_contextMenu; + RefPtr<WebOpenPanelResultListener> m_activeOpenPanelResultListener; + GeolocationPermissionRequestManager m_geolocationPermissionRequestManager; + RefPtr<NotificationPermissionRequestManager> m_notificationPermissionRequestManager; + + OwnPtr<WebCore::PrintContext> m_printContext; + + SandboxExtensionTracker m_sandboxExtensionTracker; + uint64_t m_pageID; + + RefPtr<SandboxExtension> m_pendingDropSandboxExtension; + + bool m_canRunBeforeUnloadConfirmPanel; + + bool m_canRunModal; + bool m_isRunningModal; + + bool m_cachedMainFrameIsPinnedToLeftSide; + bool m_cachedMainFrameIsPinnedToRightSide; + + unsigned m_cachedPageCount; + + bool m_isShowingContextMenu; + +#if PLATFORM(WIN) + bool m_gestureReachedScrollingLimit; +#endif +#if PLATFORM(QT) + HashMap<String, QtNetworkReply*> m_applicationSchemeReplies; +#endif +}; + +} // namespace WebKit + +#endif // WebPage_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in new file mode 100644 index 000000000..5a3bb450e --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in @@ -0,0 +1,248 @@ +# Copyright (C) 2010, 2011 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. + +messages -> WebPage { + SetActive(bool active) + SetFocused(bool focused) + SetInitialFocus(bool forward, bool isKeyboardEventValid, WebKit::WebKeyboardEvent event) + SetIsInWindow(bool isInWindow) + + SetDrawsBackground(bool drawsBackground) + SetDrawsTransparentBackground(bool drawsTransparentBackground) + + ViewWillStartLiveResize() + ViewWillEndLiveResize() + + KeyEvent(WebKit::WebKeyboardEvent event) + KeyEventSyncForTesting(WebKit::WebKeyboardEvent event) -> (bool handled) + MouseEvent(WebKit::WebMouseEvent event) + MouseEventSyncForTesting(WebKit::WebMouseEvent event) -> (bool handled) + WheelEventSyncForTesting(WebKit::WebWheelEvent event) -> (bool handled) +#if ENABLE(TOUCH_EVENTS) + TouchEvent(WebKit::WebTouchEvent event) + TouchEventSyncForTesting(WebKit::WebTouchEvent event) -> (bool handled) +#endif + + ContextMenuHidden() + + ScrollBy(uint32_t scrollDirection, uint32_t scrollGranularity) + CenterSelectionInVisibleArea() + + GoBack(uint64_t backForwardItemID, WebKit::SandboxExtension::Handle sandboxExtensionHandle) + GoForward(uint64_t backForwardItemID, WebKit::SandboxExtension::Handle sandboxExtensionHandle) + GoToBackForwardItem(uint64_t backForwardItemID, WebKit::SandboxExtension::Handle sandboxExtensionHandle) + TryRestoreScrollPosition() + LoadHTMLString(WTF::String htmlString, WTF::String baseURL) + LoadAlternateHTMLString(WTF::String htmlString, WTF::String baseURL, WTF::String unreachableURL); + LoadPlainTextString(WTF::String string) + LoadURL(WTF::String url, WebKit::SandboxExtension::Handle sandboxExtensionHandle) + LoadURLRequest(WebCore::ResourceRequest request, WebKit::SandboxExtension::Handle sandboxExtensionHandle) + LinkClicked(WTF::String url, WebKit::WebMouseEvent event) + Reload(bool reloadFromOrigin) + StopLoading() + +#if PLATFORM(QT) + ApplicationSchemeReply(WebKit::QtNetworkReplyData reply) + RegisterApplicationScheme(WTF::String scheme) +#endif + + StopLoadingFrame(uint64_t frameID) + + RestoreSession(WebKit::SessionState state) + RestoreSessionAndNavigateToCurrentItem(WebKit::SessionState state, WebKit::SandboxExtension::Handle sandboxExtensionHandle) + + DidRemoveBackForwardItem(uint64_t backForwardItemID) + + DidReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID) + + ClearSelection() + + # Callbacks. + GetContentsAsString(uint64_t callbackID) + GetMainResourceDataOfFrame(uint64_t frameID, uint64_t callbackID) + GetResourceDataFromFrame(uint64_t frameID, WTF::String resourceURL, uint64_t callbackID) + GetRenderTreeExternalRepresentation(uint64_t callbackID) + GetSelectionOrContentsAsString(uint64_t callbackID) + GetSourceForFrame(uint64_t frameID, uint64_t callbackID) + GetWebArchiveOfFrame(uint64_t frameID, uint64_t callbackID) + RunJavaScriptInMainFrame(WTF::String script, uint64_t callbackID) + ForceRepaint(uint64_t callbackID) + +#if PLATFORM(MAC) + # Dictionary support. + PerformDictionaryLookupAtLocation(WebCore::FloatPoint point) +#endif + + PreferencesDidChange(WebKit::WebPreferencesStore store) + + SetUserAgent(WTF::String userAgent) + SetCustomTextEncodingName(WTF::String encodingName) + +#if USE(TILED_BACKING_STORE) + SetFixedVisibleContentRect(WebCore::IntRect rect) + SetViewportSize(WebCore::IntSize size) +#endif + + Close() + TryClose() + + ValidateCommand(WTF::String name, uint64_t callbackID) + ExecuteEditCommand(WTF::String name) + + DidRemoveEditCommand(uint64_t commandID) + ReapplyEditCommand(uint64_t commandID) + UnapplyEditCommand(uint64_t commandID) + + SetPageAndTextZoomFactors(double pageZoomFactor, double textZoomFactor) + SetPageZoomFactor(double zoomFactor) + SetTextZoomFactor(double zoomFactor) + WindowScreenDidChange(uint64_t displayID) + + ScalePage(double scale, WebCore::IntPoint origin) + + SetUseFixedLayout(bool fixed) + SetFixedLayoutSize(WebCore::IntSize size) + + SetPaginationMode(uint32_t mode); + SetPageLength(double pageLength); + SetGapBetweenPages(double gap); + + # Find. + FindString(WTF::String string, uint32_t findOptions, unsigned maxMatchCount) + HideFindUI() + CountStringMatches(WTF::String string, uint32_t findOptions, unsigned maxMatchCount) + + # Drag and drop. +#if PLATFORM(WIN) + PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, HashMap<UINT,Vector<String>> dataMap, uint32_t flags) +#endif +#if PLATFORM(QT) || PLATFORM(GTK) + PerformDragControllerAction(uint64_t action, WebCore::DragData dragData) +#endif +#if !PLATFORM(WIN) && !PLATFORM(QT) && !PLATFORM(GTK) + PerformDragControllerAction(uint64_t action, WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t draggingSourceOperationMask, WTF::String dragStorageName, uint32_t flags, WebKit::SandboxExtension::Handle sandboxExtensionHandle) +#endif + DragEnded(WebCore::IntPoint clientPosition, WebCore::IntPoint globalPosition, uint64_t operation) + + # Popup menu. + DidChangeSelectedIndexForActivePopupMenu(int32_t newIndex); + SetTextForActivePopupMenu(int32_t index); +#if PLATFORM(GTK) + FailedToShowPopupMenu(); +#endif + + # Context menu. + DidSelectItemFromActiveContextMenu(WebKit::WebContextMenuItemData menuItem); + + # Open panel. + DidChooseFilesForOpenPanel(Vector<WTF::String> fileURLs) + DidCancelForOpenPanel() +#if ENABLE(WEB_PROCESS_SANDBOX) + ExtendSandboxForFileFromOpenPanel(WebKit::SandboxExtension::Handle sandboxExtensionHandle) +#endif + + # Spelling and grammar. + AdvanceToNextMisspelling(bool startBeforeSelection) + ChangeSpellingToWord(WTF::String word) +#if PLATFORM(MAC) + UppercaseWord(); + LowercaseWord(); + CapitalizeWord(); + + SetSmartInsertDeleteEnabled(bool isSmartInsertDeleteEnabled); +#endif + + # Geolocation + DidReceiveGeolocationPermissionDecision(uint64_t geolocationID, bool allowed) + + # Notification + DidReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed) + + SetWindowResizerSize(WebCore::IntSize intersectsView) + + # Printing. + BeginPrinting(uint64_t frameID, WebKit::PrintInfo printInfo) + EndPrinting(); + ComputePagesForPrinting(uint64_t frameID, WebKit::PrintInfo printInfo, uint64_t callbackID) +#if PLATFORM(MAC) || PLATFORM(WIN) + DrawRectToPDF(uint64_t frameID, WebKit::PrintInfo printInfo, WebCore::IntRect rect, uint64_t callbackID) + DrawPagesToPDF(uint64_t frameID, WebKit::PrintInfo printInfo, uint32_t first, uint32_t count, uint64_t callbackID) +#endif + + SetMemoryCacheMessagesEnabled(bool memoryCacheMessagesEnabled) + + // FIXME: This a dummy message, to avoid breaking the build for platforms that don't require + // any synchronous messages, and should be removed when <rdar://problem/8775115> is fixed. + Dummy() -> (bool dummyReturn) + + SetCanRunBeforeUnloadConfirmPanel(bool canRunBeforeUnloadConfirmPanel) + SetCanRunModal(bool canRunModal) + +#if PLATFORM(QT) + SetComposition(WTF::String text, WTF::Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) + ConfirmComposition(WTF::String text, int64_t selectionStart, int64_t selectionLength) + CancelComposition() +#endif + +#if PLATFORM(MAC) + # Complex text input support for plug-ins. + SendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, String textInput) + + SetWindowIsVisible(bool windowIsVisible) + WindowAndViewFramesChanged(WebCore::IntRect windowFrameInScreenCoordinates, WebCore::IntRect viewFrameInWindowCoordinates, WebCore::IntPoint accessibilityViewCoordinates) + RegisterUIProcessAccessibilityTokens(CoreIPC::DataReference elemenToken, CoreIPC::DataReference windowToken) + WriteSelectionToPasteboard(WTF::String pasteboardName, WTF::Vector<WTF::String> pasteboardTypes) -> (bool result) + ReadSelectionFromPasteboard(WTF::String pasteboardName) -> (bool result) + + # Text input. + SetComposition(WTF::String text, WTF::Vector<WebCore::CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) -> (WebKit::EditorState newState) + ConfirmComposition() -> (WebKit::EditorState newState) + CancelComposition() -> (WebKit::EditorState newState) + InsertText(WTF::String text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd) -> (bool handled, WebKit::EditorState newState) + GetMarkedRange() -> (uint64_t location, uint64_t length) + GetSelectedRange() -> (uint64_t location, uint64_t length) + GetAttributedSubstringFromRange(uint64_t location, uint64_t length) -> (WebKit::AttributedString result) + CharacterIndexForPoint(WebCore::IntPoint point) -> (uint64_t result) + FirstRectForCharacterRange(uint64_t location, uint64_t length) -> (WebCore::IntRect resultRect) + ExecuteKeypressCommands(Vector<WebCore::KeypressCommand> savedCommands) -> (bool handled, WebKit::EditorState newState) + ShouldDelayWindowOrderingEvent(WebKit::WebMouseEvent event) -> (bool result) + AcceptsFirstMouse(int eventNumber, WebKit::WebMouseEvent event) -> (bool result) +#endif +#if PLATFORM(WIN) + // FIXME: Unify with Mac counterparts. + ConfirmComposition(WTF::String compositionString) + SetComposition(WTF::String compositionString, WTF::Vector<WebCore::CompositionUnderline> underlines, uint64_t cursorPosition) + FirstRectForCharacterInSelectedRange(uint64_t characterPosition) -> (WebCore::IntRect resultRect) + GetSelectedText() -> (WTF::String text) + + GestureWillBegin(WebCore::IntPoint point) -> (bool canBeginPanning) + GestureDidScroll(WebCore::IntSize size) + GestureDidEnd() +#endif +#if PLATFORM(QT) + FindZoomableAreaForPoint(WebCore::IntPoint point) +#endif + +#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD) + HandleCorrectionPanelResult(String result) +#endif +} diff --git a/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.cpp b/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.cpp new file mode 100644 index 000000000..3bd20c8a6 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.cpp @@ -0,0 +1,48 @@ +/* + * 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 "config.h" +#include "WebPageGroupProxy.h" + +#include "WebProcess.h" +#include "InjectedBundle.h" + +namespace WebKit { + +PassRefPtr<WebPageGroupProxy> WebPageGroupProxy::create(const WebPageGroupData& data) +{ + RefPtr<WebPageGroupProxy> pageGroup = adoptRef(new WebPageGroupProxy(data)); + + if (pageGroup->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle()) + WebProcess::shared().injectedBundle()->didInitializePageGroup(pageGroup.get()); + + return pageGroup.release(); +} + +WebPageGroupProxy::~WebPageGroupProxy() +{ +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h b/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h new file mode 100644 index 000000000..91e6c5cfd --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebPageGroupProxy.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#ifndef WebPageGroupProxy_h +#define WebPageGroupProxy_h + +#include "APIObject.h" +#include "WebPageGroupData.h" +#include <wtf/PassRefPtr.h> + +namespace WebKit { + +class WebPageGroupProxy : public APIObject { +public: + static const Type APIType = TypeBundlePageGroup; + + static PassRefPtr<WebPageGroupProxy> create(const WebPageGroupData&); + virtual ~WebPageGroupProxy(); + + const String& identifier() const { return m_data.identifer; } + uint64_t pageGroupID() const { return m_data.pageGroupID; } + bool isVisibleToInjectedBundle() const { return m_data.visibleToInjectedBundle; } + bool isVisibleToHistoryClient() const { return m_data.visibleToHistoryClient; } + +private: + WebPageGroupProxy(const WebPageGroupData& data) + : m_data(data) + { + } + + virtual Type type() const { return APIType; } + + WebPageGroupData m_data; +}; + +} // namespace WebKit + +#endif // WebPageGroupProxy_h diff --git a/Source/WebKit2/WebProcess/WebPage/WebUndoStep.cpp b/Source/WebKit2/WebProcess/WebPage/WebUndoStep.cpp new file mode 100644 index 000000000..7b41c5aa6 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebUndoStep.cpp @@ -0,0 +1,42 @@ +/* + * 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 "config.h" +#include "WebUndoStep.h" + +namespace WebKit { + +static uint64_t generateUndoStep() +{ + static uint64_t uniqueEntryID = 1; + return uniqueEntryID++; +} + +PassRefPtr<WebUndoStep> WebUndoStep::create(PassRefPtr<WebCore::UndoStep> step) +{ + return adoptRef(new WebUndoStep(step, generateUndoStep())); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/WebUndoStep.h b/Source/WebKit2/WebProcess/WebPage/WebUndoStep.h new file mode 100644 index 000000000..745377a3c --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/WebUndoStep.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef WebUndoStep_h +#define WebUndoStep_h + +#include <WebCore/UndoStep.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefPtr.h> + +namespace WebKit { + +class WebUndoStep : public RefCounted<WebUndoStep> { +public: + static PassRefPtr<WebUndoStep> create(PassRefPtr<WebCore::UndoStep>); + + WebCore::UndoStep* step() const { return m_step.get(); } + uint64_t stepID() const { return m_stepID; } + +private: + WebUndoStep(PassRefPtr<WebCore::UndoStep> step, uint64_t stepID) + : m_step(step) + , m_stepID(stepID) + { + } + + RefPtr<WebCore::UndoStep> m_step; + uint64_t m_stepID; +}; + +} // namespace WebKit + +#endif // WebEditCommand_h diff --git a/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp new file mode 100644 index 000000000..8b135fd06 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "LayerTreeHostCA.h" + +#include "DrawingAreaImpl.h" +#include "WebPage.h" +#include "WebProcess.h" +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/GraphicsLayerCA.h> +#include <WebCore/Page.h> +#include <WebCore/PlatformCALayer.h> +#include <WebCore/Settings.h> + +using namespace WebCore; + +namespace WebKit { + +LayerTreeHostCA::LayerTreeHostCA(WebPage* webPage) + : LayerTreeHost(webPage) + , m_layerFlushSchedulingEnabled(true) + , m_isValid(true) + , m_notifyAfterScheduledLayerFlush(false) +{ +} + +void LayerTreeHostCA::initialize() +{ + // Create a root layer. + m_rootLayer = GraphicsLayer::create(this); +#ifndef NDEBUG + m_rootLayer->setName("LayerTreeHost root layer"); +#endif + m_rootLayer->setDrawsContent(false); + m_rootLayer->setSize(m_webPage->size()); + static_cast<GraphicsLayerCA*>(m_rootLayer.get())->platformCALayer()->setGeometryFlipped(true); + + m_nonCompositedContentLayer = GraphicsLayer::create(this); + static_cast<GraphicsLayerCA*>(m_nonCompositedContentLayer.get())->setAllowTiledLayer(false); +#ifndef NDEBUG + m_nonCompositedContentLayer->setName("LayerTreeHost non-composited content"); +#endif + m_nonCompositedContentLayer->setDrawsContent(true); + m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground()); + m_nonCompositedContentLayer->setSize(m_webPage->size()); + if (m_webPage->corePage()->settings()->acceleratedDrawingEnabled()) + m_nonCompositedContentLayer->setAcceleratesDrawing(true); + + m_rootLayer->addChild(m_nonCompositedContentLayer.get()); + + if (m_webPage->hasPageOverlay()) + createPageOverlayLayer(); + + platformInitialize(m_layerTreeContext); + + setLayerFlushSchedulingEnabled(!m_webPage->drawingArea() || !m_webPage->drawingArea()->layerTreeStateIsFrozen()); + scheduleLayerFlush(); +} + +LayerTreeHostCA::~LayerTreeHostCA() +{ + ASSERT(!m_isValid); + ASSERT(!m_rootLayer); +} + +const LayerTreeContext& LayerTreeHostCA::layerTreeContext() +{ + return m_layerTreeContext; +} + +void LayerTreeHostCA::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush) +{ + m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush; +} + +void LayerTreeHostCA::setRootCompositingLayer(GraphicsLayer* graphicsLayer) +{ + m_nonCompositedContentLayer->removeAllChildren(); + + // Add the accelerated layer tree hierarchy. + if (graphicsLayer) + m_nonCompositedContentLayer->addChild(graphicsLayer); +} + +void LayerTreeHostCA::invalidate() +{ + ASSERT(m_isValid); + m_rootLayer = nullptr; + m_isValid = false; +} + +void LayerTreeHostCA::setNonCompositedContentsNeedDisplay(const IntRect& rect) +{ + m_nonCompositedContentLayer->setNeedsDisplayInRect(rect); + if (m_pageOverlayLayer) + m_pageOverlayLayer->setNeedsDisplayInRect(rect); + + scheduleLayerFlush(); +} + +void LayerTreeHostCA::scrollNonCompositedContents(const IntRect& scrollRect, const IntSize& scrollOffset) +{ + setNonCompositedContentsNeedDisplay(scrollRect); +} + +void LayerTreeHostCA::sizeDidChange(const IntSize& newSize) +{ + m_rootLayer->setSize(newSize); + + // If the newSize exposes new areas of the non-composited content a setNeedsDisplay is needed + // for those newly exposed areas. + FloatSize oldSize = m_nonCompositedContentLayer->size(); + m_nonCompositedContentLayer->setSize(newSize); + + if (newSize.width() > oldSize.width()) { + float height = std::min(static_cast<float>(newSize.height()), oldSize.height()); + m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(oldSize.width(), 0, newSize.width() - oldSize.width(), height)); + } + + if (newSize.height() > oldSize.height()) + m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height())); + + if (m_pageOverlayLayer) + m_pageOverlayLayer->setSize(newSize); + + scheduleLayerFlush(); + flushPendingLayerChanges(); +} + +void LayerTreeHostCA::deviceScaleFactorDidChange() +{ + // Other layers learn of the scale factor change via WebPage::setDeviceScaleFactor. + m_nonCompositedContentLayer->deviceOrPageScaleFactorChanged(); +} + +void LayerTreeHostCA::forceRepaint() +{ + scheduleLayerFlush(); + flushPendingLayerChanges(); +} + +void LayerTreeHostCA::didInstallPageOverlay() +{ + createPageOverlayLayer(); + scheduleLayerFlush(); +} + +void LayerTreeHostCA::didUninstallPageOverlay() +{ + destroyPageOverlayLayer(); + scheduleLayerFlush(); +} + +void LayerTreeHostCA::setPageOverlayNeedsDisplay(const IntRect& rect) +{ + ASSERT(m_pageOverlayLayer); + m_pageOverlayLayer->setNeedsDisplayInRect(rect); + scheduleLayerFlush(); +} + +void LayerTreeHostCA::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time) +{ +} + +void LayerTreeHostCA::notifySyncRequired(const WebCore::GraphicsLayer*) +{ +} + +void LayerTreeHostCA::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& graphicsContext, GraphicsLayerPaintingPhase, const IntRect& clipRect) +{ + if (graphicsLayer == m_nonCompositedContentLayer) { + m_webPage->drawRect(graphicsContext, clipRect); + return; + } + + if (graphicsLayer == m_pageOverlayLayer) { + m_webPage->drawPageOverlay(graphicsContext, clipRect); + return; + } +} + +bool LayerTreeHostCA::showDebugBorders() const +{ + return m_webPage->corePage()->settings()->showDebugBorders(); +} + +bool LayerTreeHostCA::showRepaintCounter() const +{ + return m_webPage->corePage()->settings()->showRepaintCounter(); +} + +float LayerTreeHostCA::deviceScaleFactor() const +{ + return m_webPage->corePage()->deviceScaleFactor(); +} + +void LayerTreeHostCA::performScheduledLayerFlush() +{ + { + RefPtr<LayerTreeHostCA> protect(this); + m_webPage->layoutIfNeeded(); + + if (!m_isValid) + return; + } + + if (!flushPendingLayerChanges()) + return; + + didPerformScheduledLayerFlush(); +} + +void LayerTreeHostCA::didPerformScheduledLayerFlush() +{ + if (m_notifyAfterScheduledLayerFlush) { + // Let the drawing area know that we've done a flush of the layer changes. + static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers(); + m_notifyAfterScheduledLayerFlush = false; + } +} + +bool LayerTreeHostCA::flushPendingLayerChanges() +{ + m_rootLayer->syncCompositingStateForThisLayerOnly(); + m_nonCompositedContentLayer->syncCompositingStateForThisLayerOnly(); + if (m_pageOverlayLayer) + m_pageOverlayLayer->syncCompositingStateForThisLayerOnly(); + + return m_webPage->corePage()->mainFrame()->view()->syncCompositingStateIncludingSubframes(); +} + +void LayerTreeHostCA::createPageOverlayLayer() +{ + ASSERT(!m_pageOverlayLayer); + + m_pageOverlayLayer = GraphicsLayer::create(this); +#ifndef NDEBUG + m_pageOverlayLayer->setName("LayerTreeHost page overlay content"); +#endif + + m_pageOverlayLayer->setDrawsContent(true); + m_pageOverlayLayer->setSize(m_webPage->size()); + + m_rootLayer->addChild(m_pageOverlayLayer.get()); +} + +void LayerTreeHostCA::destroyPageOverlayLayer() +{ + ASSERT(m_pageOverlayLayer); + m_pageOverlayLayer->removeFromParent(); + m_pageOverlayLayer = nullptr; +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h new file mode 100644 index 000000000..0566e9733 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/LayerTreeHostCA.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef LayerTreeHostCA_h +#define LayerTreeHostCA_h + +#include "LayerTreeContext.h" +#include "LayerTreeHost.h" +#include <WebCore/GraphicsLayerClient.h> +#include <wtf/OwnPtr.h> + +namespace WebKit { + +class LayerTreeHostCA : public LayerTreeHost, WebCore::GraphicsLayerClient { +public: + virtual ~LayerTreeHostCA(); + +protected: + explicit LayerTreeHostCA(WebPage*); + + WebCore::GraphicsLayer* rootLayer() const { return m_rootLayer.get(); } + + void initialize(); + void performScheduledLayerFlush(); + + // LayerTreeHost. + virtual void invalidate(); + virtual void sizeDidChange(const WebCore::IntSize& newSize); + virtual void deviceScaleFactorDidChange(); + virtual void forceRepaint(); + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*); + + // LayerTreeHostCA + virtual void didPerformScheduledLayerFlush(); + + bool m_layerFlushSchedulingEnabled; + +private: + // LayerTreeHost. + virtual const LayerTreeContext& layerTreeContext(); + virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool); + + virtual void setNonCompositedContentsNeedDisplay(const WebCore::IntRect&); + virtual void scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset); + + virtual void didInstallPageOverlay(); + virtual void didUninstallPageOverlay(); + virtual void setPageOverlayNeedsDisplay(const WebCore::IntRect&); + + // GraphicsLayerClient + virtual void notifyAnimationStarted(const WebCore::GraphicsLayer*, double time); + virtual void notifySyncRequired(const WebCore::GraphicsLayer*); + virtual void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect); + virtual bool showDebugBorders() const; + virtual bool showRepaintCounter() const; + virtual float deviceScaleFactor() const; + virtual void didCommitChangesForLayer(const WebCore::GraphicsLayer*) const { } + + // LayerTreeHostCA + virtual void platformInitialize(LayerTreeContext&) = 0; + + bool flushPendingLayerChanges(); + + void createPageOverlayLayer(); + void destroyPageOverlayLayer(); + + // The context for this layer tree. + LayerTreeContext m_layerTreeContext; + + // Whether the layer tree host is valid or not. + bool m_isValid; + + // Whether we should let the drawing area know the next time we've flushed + // layer tree changes. + bool m_notifyAfterScheduledLayerFlush; + + // The root layer. + OwnPtr<WebCore::GraphicsLayer> m_rootLayer; + + // The layer which contains all non-composited content. + OwnPtr<WebCore::GraphicsLayer> m_nonCompositedContentLayer; + + // The page overlay layer. Will be null if there's no page overlay. + OwnPtr<WebCore::GraphicsLayer> m_pageOverlayLayer; +}; + +} // namespace WebKit + +#endif // LayerTreeHostCA_h diff --git a/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h new file mode 100644 index 000000000..06759e25d --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef LayerTreeHostCAMac_h +#define LayerTreeHostCAMac_h + +#include "LayerTreeHostCA.h" +#include <WebCore/LayerFlushScheduler.h> +#include <WebCore/LayerFlushSchedulerClient.h> +#include <wtf/RetainPtr.h> + +typedef struct __WKCARemoteLayerClientRef* WKCARemoteLayerClientRef; + +namespace WebKit { + +class LayerTreeHostCAMac : public LayerTreeHostCA, public WebCore::LayerFlushSchedulerClient { +public: + static PassRefPtr<LayerTreeHostCAMac> create(WebPage*); + virtual ~LayerTreeHostCAMac(); + +private: + explicit LayerTreeHostCAMac(WebPage*); + + // LayerTreeHost. + virtual void scheduleLayerFlush(); + virtual void setLayerFlushSchedulingEnabled(bool); + virtual void invalidate(); + virtual void sizeDidChange(const WebCore::IntSize& newSize); + virtual void forceRepaint(); + virtual void pauseRendering(); + virtual void resumeRendering(); + + // LayerTreeHostCA + virtual void platformInitialize(LayerTreeContext&); + virtual void didPerformScheduledLayerFlush(); + + // LayerFlushSchedulerClient + virtual bool flushLayers(); + + RetainPtr<WKCARemoteLayerClientRef> m_remoteLayerClient; + WebCore::LayerFlushScheduler m_layerFlushScheduler; +}; + +} // namespace WebKit + +#endif // LayerTreeHostCAMac_h diff --git a/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm new file mode 100644 index 000000000..5ff8ad13b --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/mac/LayerTreeHostCAMac.mm @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2011 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. + */ + +#import "config.h" +#import "LayerTreeHostCAMac.h" + +#import "WebProcess.h" +#import <QuartzCore/CATransaction.h> +#import <WebCore/GraphicsLayer.h> +#import <WebKitSystemInterface.h> + +using namespace WebCore; + +@interface CATransaction (Details) ++ (void)synchronize; +@end + +namespace WebKit { + +PassRefPtr<LayerTreeHostCAMac> LayerTreeHostCAMac::create(WebPage* webPage) +{ + RefPtr<LayerTreeHostCAMac> host = adoptRef(new LayerTreeHostCAMac(webPage)); + host->initialize(); + return host.release(); +} + +LayerTreeHostCAMac::LayerTreeHostCAMac(WebPage* webPage) + : LayerTreeHostCA(webPage) + , m_layerFlushScheduler(this) +{ +} + +LayerTreeHostCAMac::~LayerTreeHostCAMac() +{ + ASSERT(!m_remoteLayerClient); +} + +void LayerTreeHostCAMac::platformInitialize(LayerTreeContext& layerTreeContext) +{ + mach_port_t serverPort = WebProcess::shared().compositingRenderServerPort(); + m_remoteLayerClient = WKCARemoteLayerClientMakeWithServerPort(serverPort); + + WKCARemoteLayerClientSetLayer(m_remoteLayerClient.get(), rootLayer()->platformLayer()); + + layerTreeContext.contextID = WKCARemoteLayerClientGetClientId(m_remoteLayerClient.get()); +} + +void LayerTreeHostCAMac::scheduleLayerFlush() +{ + m_layerFlushScheduler.schedule(); +} + +void LayerTreeHostCAMac::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled) +{ + if (layerFlushingEnabled) + m_layerFlushScheduler.resume(); + else + m_layerFlushScheduler.suspend(); +} + +void LayerTreeHostCAMac::invalidate() +{ + m_layerFlushScheduler.invalidate(); + + WKCARemoteLayerClientInvalidate(m_remoteLayerClient.get()); + m_remoteLayerClient = nullptr; + + LayerTreeHostCA::invalidate(); +} + +void LayerTreeHostCAMac::sizeDidChange(const IntSize& newSize) +{ + LayerTreeHostCA::sizeDidChange(newSize); + [CATransaction flush]; + [CATransaction synchronize]; +} + +void LayerTreeHostCAMac::forceRepaint() +{ + LayerTreeHostCA::forceRepaint(); + [CATransaction flush]; + [CATransaction synchronize]; +} + +void LayerTreeHostCAMac::pauseRendering() +{ + CALayer* root = rootLayer()->platformLayer(); + [root setValue:(id)kCFBooleanTrue forKey:@"NSCAViewRenderPaused"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"NSCAViewRenderDidPauseNotification" object:nil userInfo:[NSDictionary dictionaryWithObject:root forKey:@"layer"]]; +} + +void LayerTreeHostCAMac::resumeRendering() +{ + CALayer* root = rootLayer()->platformLayer(); + [root setValue:(id)kCFBooleanFalse forKey:@"NSCAViewRenderPaused"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"NSCAViewRenderDidResumeNotification" object:nil userInfo:[NSDictionary dictionaryWithObject:root forKey:@"layer"]]; +} + +bool LayerTreeHostCAMac::flushLayers() +{ + // This gets called outside of the normal event loop so wrap in an autorelease pool + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + performScheduledLayerFlush(); + [pool drain]; + + return true; +} + +void LayerTreeHostCAMac::didPerformScheduledLayerFlush() +{ + LayerTreeHostCA::didPerformScheduledLayerFlush(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp new file mode 100644 index 000000000..ef3c16a11 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "LayerTreeHostCAWin.h" + +#if HAVE(WKQCA) + +#include "DrawingAreaImpl.h" +#include "ShareableBitmap.h" +#include "UpdateInfo.h" +#include "WKCACFViewWindow.h" +#include "WebPage.h" +#include <WebCore/GraphicsLayerCA.h> +#include <WebCore/LayerChangesFlusher.h> +#include <WebCore/PlatformCALayer.h> +#include <WebCore/WebCoreInstanceHandle.h> +#include <WebKitQuartzCoreAdditions/WKCACFImage.h> +#include <WebKitQuartzCoreAdditions/WKCACFView.h> +#include <wtf/CurrentTime.h> +#include <wtf/MainThread.h> + +#ifdef DEBUG_ALL +#pragma comment(lib, "WebKitQuartzCoreAdditions_debug") +#else +#pragma comment(lib, "WebKitQuartzCoreAdditions") +#endif + +using namespace WebCore; + +namespace WebKit { + +bool LayerTreeHostCAWin::supportsAcceleratedCompositing() +{ + static bool initialized; + static bool supportsAcceleratedCompositing; + if (initialized) + return supportsAcceleratedCompositing; + initialized = true; + + RetainPtr<WKCACFViewRef> view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow)); + WKCACFViewWindow dummyWindow(view.get(), 0, 0); + CGRect fakeBounds = CGRectMake(0, 0, 10, 10); + WKCACFViewUpdate(view.get(), dummyWindow.window(), &fakeBounds); + + supportsAcceleratedCompositing = WKCACFViewCanDraw(view.get()); + + WKCACFViewUpdate(view.get(), 0, 0); + + return supportsAcceleratedCompositing; +} + +PassRefPtr<LayerTreeHostCAWin> LayerTreeHostCAWin::create(WebPage* webPage) +{ + RefPtr<LayerTreeHostCAWin> host = adoptRef(new LayerTreeHostCAWin(webPage)); + host->initialize(); + return host.release(); +} + +LayerTreeHostCAWin::LayerTreeHostCAWin(WebPage* webPage) + : LayerTreeHostCA(webPage) + , m_isFlushingLayerChanges(false) +{ +} + +LayerTreeHostCAWin::~LayerTreeHostCAWin() +{ +} + +void LayerTreeHostCAWin::platformInitialize(LayerTreeContext& context) +{ + m_view.adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow)); + WKCACFViewSetContextUserData(m_view.get(), static_cast<AbstractCACFLayerTreeHost*>(this)); + WKCACFViewSetLayer(m_view.get(), rootLayer()->platformLayer()); + WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this); + + // Passing WS_DISABLED makes the window invisible to mouse events, which lets WKView's normal + // event handling mechanism work even when this window is obscuring the entire WKView HWND. + // Note that m_webPage->nativeWindow() is owned by the UI process, so this creates a cross- + // process window hierarchy (and thus implicitly attaches the input queues of the UI and web + // processes' main threads). + m_window = adoptPtr(new WKCACFViewWindow(m_view.get(), m_webPage->nativeWindow(), WS_DISABLED)); + + CGRect bounds = m_webPage->bounds(); + WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds); + + context.window = m_window->window(); +} + +void LayerTreeHostCAWin::invalidate() +{ + LayerChangesFlusher::shared().cancelPendingFlush(this); + + WKCACFViewSetContextUserData(m_view.get(), 0); + WKCACFViewSetLayer(m_view.get(), 0); + WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0); + + // The UI process will destroy m_window's HWND when it gets the message to switch out of + // accelerated compositing mode. We don't want to destroy the HWND before then or we will get a + // flash of white before the UI process has a chance to display the non-composited content. + // Since the HWND needs to outlive us, we leak m_window here and tell it to clean itself up + // when its HWND is destroyed. + WKCACFViewWindow* window = m_window.leakPtr(); + window->setDeletesSelfWhenWindowDestroyed(true); + + LayerTreeHostCA::invalidate(); +} + +void LayerTreeHostCAWin::scheduleLayerFlush() +{ + if (!m_layerFlushSchedulingEnabled) + return; + + LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this); +} + +void LayerTreeHostCAWin::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled) +{ + if (m_layerFlushSchedulingEnabled == layerFlushingEnabled) + return; + + m_layerFlushSchedulingEnabled = layerFlushingEnabled; + + if (m_layerFlushSchedulingEnabled) { + scheduleLayerFlush(); + return; + } + + LayerChangesFlusher::shared().cancelPendingFlush(this); +} + +void LayerTreeHostCAWin::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry) +{ + m_geometriesUpdater.addPendingUpdate(geometry); +} + +void LayerTreeHostCAWin::sizeDidChange(const IntSize& newSize) +{ + LayerTreeHostCA::sizeDidChange(newSize); + CGRect bounds = CGRectMake(0, 0, newSize.width(), newSize.height()); + WKCACFViewUpdate(m_view.get(), m_window->window(), &bounds); + WKCACFViewFlushContext(m_view.get()); +} + +void LayerTreeHostCAWin::forceRepaint() +{ + LayerTreeHostCA::forceRepaint(); + WKCACFViewFlushContext(m_view.get()); +} + +void LayerTreeHostCAWin::contextDidChangeCallback(WKCACFViewRef view, void* info) +{ + // This should only be called on a background thread when no changes have actually + // been committed to the context, eg. when a video frame has been added to an image + // queue, so return without triggering animations etc. + if (!isMainThread()) + return; + + LayerTreeHostCAWin* host = static_cast<LayerTreeHostCAWin*>(info); + ASSERT_ARG(view, view == host->m_view); + host->contextDidChange(); +} + +void LayerTreeHostCAWin::contextDidChange() +{ + // Send currentTime to the pending animations. This function is called by CACF in a callback + // which occurs after the drawInContext calls. So currentTime is very close to the time + // the animations actually start + double currentTime = WTF::currentTime(); + + HashSet<RefPtr<PlatformCALayer> >::iterator end = m_pendingAnimatedLayers.end(); + for (HashSet<RefPtr<PlatformCALayer> >::iterator it = m_pendingAnimatedLayers.begin(); it != end; ++it) + (*it)->animationStarted(currentTime); + + m_pendingAnimatedLayers.clear(); + + // Update child window geometries now so that they stay mostly in sync with the accelerated content. + // FIXME: We should really be doing this when the changes we just flushed appear on screen. <http://webkit.org/b/61867> + // We also bring the child windows (i.e., plugins) to the top of the z-order to ensure they are above m_window. + // FIXME: We could do this just once per window when it is first shown. Maybe that would be more efficient? + m_geometriesUpdater.updateGeometries(BringToTop); +} + +PlatformCALayer* LayerTreeHostCAWin::rootLayer() const +{ + return static_cast<GraphicsLayerCA*>(LayerTreeHostCA::rootLayer())->platformCALayer(); +} + +void LayerTreeHostCAWin::addPendingAnimatedLayer(PassRefPtr<PlatformCALayer> layer) +{ + m_pendingAnimatedLayers.add(layer); +} + +void LayerTreeHostCAWin::layerTreeDidChange() +{ + if (m_isFlushingLayerChanges) { + // The layer tree is changing as a result of flushing GraphicsLayer changes to their + // underlying PlatformCALayers. We'll flush those changes to the context as part of that + // process, so there's no need to schedule another flush here. + return; + } + + // The layer tree is changing as a result of someone modifying a PlatformCALayer that doesn't + // have a corresponding GraphicsLayer. Schedule a flush since we won't schedule one through the + // normal GraphicsLayer mechanisms. + LayerChangesFlusher::shared().flushPendingLayerChangesSoon(this); +} + +void LayerTreeHostCAWin::flushPendingLayerChangesNow() +{ + RefPtr<LayerTreeHostCA> protector(this); + + m_isFlushingLayerChanges = true; + + // Flush changes stored up in GraphicsLayers to their underlying PlatformCALayers, if + // requested. + performScheduledLayerFlush(); + + // Flush changes stored up in PlatformCALayers to the context so they will be rendered. + WKCACFViewFlushContext(m_view.get()); + + m_isFlushingLayerChanges = false; +} + +void LayerTreeHostCAWin::setRootCompositingLayer(GraphicsLayer* graphicsLayer) +{ + // Don't flush any changes when we don't have a root layer. This will prevent flashes of white + // when switching out of compositing mode. + setLayerFlushSchedulingEnabled(graphicsLayer); + + // Resubmit all existing animations. CACF does not remember running animations + // When the layer tree is removed and then added back to the hierarchy + if (graphicsLayer) + static_cast<GraphicsLayerCA*>(graphicsLayer)->platformCALayer()->ensureAnimationsSubmitted(); + + LayerTreeHostCA::setRootCompositingLayer(graphicsLayer); +} + +} // namespace WebKit + +#endif // HAVE(WKQCA) diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h new file mode 100644 index 000000000..d9d59678a --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/win/LayerTreeHostCAWin.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef LayerTreeHostCAWin_h +#define LayerTreeHostCAWin_h + +#include "HeaderDetection.h" + +#if HAVE(WKQCA) + +#include "CoalescedWindowGeometriesUpdater.h" +#include "LayerTreeHostCA.h" +#include <WebCore/AbstractCACFLayerTreeHost.h> +#include <wtf/HashSet.h> +#include <wtf/RetainPtr.h> + +typedef struct _WKCACFView* WKCACFViewRef; + +namespace WebKit { + +class WKCACFViewWindow; + +class LayerTreeHostCAWin : public LayerTreeHostCA, private WebCore::AbstractCACFLayerTreeHost { +public: + static bool supportsAcceleratedCompositing(); + + static PassRefPtr<LayerTreeHostCAWin> create(WebPage*); + virtual ~LayerTreeHostCAWin(); + +private: + explicit LayerTreeHostCAWin(WebPage*); + + static void contextDidChangeCallback(WKCACFViewRef, void* info); + void contextDidChange(); + + // LayerTreeHost + virtual void invalidate(); + virtual void forceRepaint(); + virtual void sizeDidChange(const WebCore::IntSize& newSize); + virtual void scheduleLayerFlush(); + virtual void setLayerFlushSchedulingEnabled(bool); + virtual void scheduleChildWindowGeometryUpdate(const WindowGeometry&); + + // LayerTreeHostCA + virtual void platformInitialize(LayerTreeContext&); + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*); + + // AbstractCACFLayerTreeHost + virtual WebCore::PlatformCALayer* rootLayer() const; + virtual void addPendingAnimatedLayer(PassRefPtr<WebCore::PlatformCALayer>); + virtual void layerTreeDidChange(); + virtual void flushPendingLayerChangesNow(); + + OwnPtr<WKCACFViewWindow> m_window; + RetainPtr<WKCACFViewRef> m_view; + HashSet<RefPtr<WebCore::PlatformCALayer> > m_pendingAnimatedLayers; + bool m_isFlushingLayerChanges; + CoalescedWindowGeometriesUpdater m_geometriesUpdater; +}; + +} // namespace WebKit + +#endif // HAVE(WKQCA) + +#endif // LayerTreeHostCAWin_h diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp b/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp new file mode 100644 index 000000000..0ce37c449 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "WKCACFViewWindow.h" + +#if HAVE(WKQCA) + +#include <WebCore/WebCoreInstanceHandle.h> +#include <WebKitQuartzCoreAdditions/WKCACFView.h> + +using namespace WebCore; + +namespace WebKit { + +static LPCWSTR windowClassName = L"WKCACFViewWindowClass"; + +WKCACFViewWindow::WKCACFViewWindow(WKCACFViewRef view, HWND parentWindow, DWORD additionalStyles) + : m_window(0) + , m_view(view) + , m_deletesSelfWhenWindowDestroyed(false) +{ + ASSERT_ARG(view, view); + + registerClass(); + + UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | additionalStyles; + if (parentWindow) + style |= WS_CHILD; + else + style |= WS_POPUP; + + m_window = ::CreateWindowExW(0, windowClassName, L"WKCACFViewWindow", style, 0, 0, 0, 0, parentWindow, 0, instanceHandle(), this); + ASSERT_WITH_MESSAGE(m_window, "::CreateWindowExW failed with error %lu", ::GetLastError()); +} + +WKCACFViewWindow::~WKCACFViewWindow() +{ + if (!m_window) + return; + + ASSERT(!m_deletesSelfWhenWindowDestroyed); + ::DestroyWindow(m_window); +} + +LRESULT WKCACFViewWindow::onCustomDestroy(WPARAM, LPARAM) +{ + ::DestroyWindow(m_window); + return 0; +} + +LRESULT WKCACFViewWindow::onDestroy(WPARAM, LPARAM) +{ + WKCACFViewUpdate(m_view.get(), 0, 0); + return 0; +} + +LRESULT WKCACFViewWindow::onEraseBackground(WPARAM, LPARAM) +{ + // Tell Windows not to erase us. + return 1; +} + +LRESULT WKCACFViewWindow::onNCDestroy(WPARAM, LPARAM) +{ + m_window = 0; + + if (!m_deletesSelfWhenWindowDestroyed) + return 0; + + delete this; + return 0; +} + +LRESULT WKCACFViewWindow::onPaint(WPARAM, LPARAM) +{ + WKCACFViewDraw(m_view.get()); + ::ValidateRect(m_window, 0); + return 0; +} + +LRESULT WKCACFViewWindow::onPrintClient(WPARAM wParam, LPARAM lParam) +{ + if (!(lParam & PRF_CLIENT)) + return 0; + + WKCACFViewDrawIntoDC(m_view.get(), reinterpret_cast<HDC>(wParam)); + return 0; +} + +void WKCACFViewWindow::registerClass() +{ + static bool didRegister; + if (didRegister) + return; + didRegister = true; + + WNDCLASSW wndClass = {0}; + wndClass.lpfnWndProc = staticWndProc; + wndClass.hInstance = instanceHandle(); + wndClass.lpszClassName = windowClassName; + + ::RegisterClassW(&wndClass); +} + +LRESULT WKCACFViewWindow::staticWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + WKCACFViewWindow* window = reinterpret_cast<WKCACFViewWindow*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (!window) { + if (message != WM_CREATE) + return ::DefWindowProcW(hWnd, message, wParam, lParam); + CREATESTRUCT* createStruct = reinterpret_cast<CREATESTRUCT*>(lParam); + window = static_cast<WKCACFViewWindow*>(createStruct->lpCreateParams); + ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(window)); + } + + return window->wndProc(message, wParam, lParam); +} + +LRESULT WKCACFViewWindow::wndProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case customDestroyMessage: + return onCustomDestroy(wParam, lParam); + case WM_DESTROY: + return onDestroy(wParam, lParam); + case WM_ERASEBKGND: + return onEraseBackground(wParam, lParam); + case WM_NCDESTROY: + return onNCDestroy(wParam, lParam); + case WM_PAINT: + return onPaint(wParam, lParam); + case WM_PRINTCLIENT: + return onPrintClient(wParam, lParam); + default: + return ::DefWindowProcW(m_window, message, wParam, lParam); + } +} + +} // namespace WebKit + +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.h b/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.h new file mode 100644 index 000000000..391146a4c --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/ca/win/WKCACFViewWindow.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef WKCACFViewWindow_h +#define WKCACFViewWindow_h + +#include "HeaderDetection.h" + +#if HAVE(WKQCA) + +#include <wtf/Noncopyable.h> +#include <wtf/RetainPtr.h> + +typedef struct _WKCACFView* WKCACFViewRef; + +namespace WebKit { + +// FIXME: Move this class down to WebCore. (Maybe it can even replace some of WKCACFViewLayerTreeHost.) +class WKCACFViewWindow { + WTF_MAKE_NONCOPYABLE(WKCACFViewWindow); +public: + // WKCACFViewWindow will destroy its HWND when this message is received. + static const UINT customDestroyMessage = WM_USER + 1; + + WKCACFViewWindow(WKCACFViewRef, HWND parentWindow, DWORD additionalStyles); + ~WKCACFViewWindow(); + + void setDeletesSelfWhenWindowDestroyed(bool deletes) { m_deletesSelfWhenWindowDestroyed = deletes; } + + HWND window() const { return m_window; } + +private: + LRESULT onCustomDestroy(WPARAM, LPARAM); + LRESULT onDestroy(WPARAM, LPARAM); + LRESULT onEraseBackground(WPARAM, LPARAM); + LRESULT onNCDestroy(WPARAM, LPARAM); + LRESULT onPaint(WPARAM, LPARAM); + LRESULT onPrintClient(WPARAM, LPARAM); + static void registerClass(); + static LRESULT CALLBACK staticWndProc(HWND, UINT, WPARAM, LPARAM); + LRESULT wndProc(UINT, WPARAM, LPARAM); + + HWND m_window; + RetainPtr<WKCACFViewRef> m_view; + bool m_deletesSelfWhenWindowDestroyed; +}; + +} // namespace WebKit + +#endif // HAVE(WKQCA) + +#endif // WKCACFViewWindow_h diff --git a/Source/WebKit2/WebProcess/WebPage/efl/WebInspectorEfl.cpp b/Source/WebKit2/WebProcess/WebPage/efl/WebInspectorEfl.cpp new file mode 100644 index 000000000..755b4268c --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/efl/WebInspectorEfl.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * + * 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 "config.h" +#include "WebInspector.h" + +#if ENABLE(INSPECTOR) + +#include <WebCore/NotImplemented.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +String WebInspector::localizedStringsURL() const +{ + notImplemented(); + return String(); +} + +} // namespace WebKit + +#endif // ENABLE(INSPECTOR) diff --git a/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp b/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp new file mode 100644 index 000000000..669442014 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * Copyright (C) 2011 Igalia S.L. + * + * 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 "config.h" +#include "WebPage.h" + +#include "NotImplemented.h" +#include "WebEvent.h" +#include "WindowsKeyboardCodes.h" +#include <WebCore/FocusController.h> +#include <WebCore/Frame.h> +#include <WebCore/KeyboardEvent.h> +#include <WebCore/Page.h> +#include <WebCore/PlatformKeyboardEvent.h> +#include <WebCore/Settings.h> + +using namespace WebCore; + +namespace WebKit { + +void WebPage::platformInitialize() +{ + notImplemented(); +} + +void WebPage::platformPreferencesDidChange(const WebPreferencesStore&) +{ + notImplemented(); +} + +static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) +{ + page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity); +} + +bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) +{ + notImplemented(); + return false; +} + +bool WebPage::platformHasLocalDataForURL(const KURL&) +{ + notImplemented(); + return false; +} + +String WebPage::cachedResponseMIMETypeForURL(const KURL&) +{ + notImplemented(); + return String(); +} + +bool WebPage::platformCanHandleRequest(const ResourceRequest&) +{ + notImplemented(); + return true; +} + +String WebPage::cachedSuggestedFilenameForURL(const KURL&) +{ + notImplemented(); + return String(); +} + +PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&) +{ + notImplemented(); + return 0; +} + +const char* WebPage::interpretKeyEvent(const KeyboardEvent* evt) +{ + notImplemented(); + return 0; +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/ChunkedUpdateDrawingAreaGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/ChunkedUpdateDrawingAreaGtk.cpp new file mode 100644 index 000000000..313ad3fe7 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/ChunkedUpdateDrawingAreaGtk.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * Copyright (C) 2011 Igalia S.L. + * + * 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 "config.h" +#include "ChunkedUpdateDrawingArea.h" + +#include "RefPtrCairo.h" +#include "UpdateChunk.h" +#include "WebPage.h" + +#include <WebCore/GraphicsContext.h> +#include <WebCore/IntRect.h> + +using namespace WebCore; + +namespace WebKit { + +void ChunkedUpdateDrawingArea::paintIntoUpdateChunk(UpdateChunk* updateChunk) +{ + ASSERT(!updateChunk->isEmpty()); + + RefPtr<cairo_surface_t> image = updateChunk->createImage(); + RefPtr<cairo_t> cr = cairo_create(image.get()); + GraphicsContext gc(cr.get()); + gc.save(); + IntRect rect = updateChunk->rect(); + gc.translate(-rect.x(), -rect.y()); + m_webPage->drawRect(gc, updateChunk->rect()); + gc.restore(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorGtk.cpp new file mode 100644 index 000000000..e00e437bd --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebInspectorGtk.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, 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 "config.h" +#include "WebInspector.h" + +#if ENABLE(INSPECTOR) + +#include <WebCore/NotImplemented.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +String WebInspector::localizedStringsURL() const +{ + notImplemented(); + return String(); +} + +} // namespace WebKit + +#endif // ENABLE(INSPECTOR) diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp new file mode 100644 index 000000000..a25e1f7b3 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. + * Copyright (C) 2011 Igalia S.L. + * + * 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 "config.h" +#include "WebPage.h" + +#include "NotImplemented.h" +#include "WebEvent.h" +#include "WindowsKeyboardCodes.h" +#include <WebCore/FocusController.h> +#include <WebCore/Frame.h> +#include <WebCore/KeyboardEvent.h> +#include <WebCore/Page.h> +#include <WebCore/PlatformKeyboardEvent.h> +#include <WebCore/Settings.h> + +using namespace WebCore; + +namespace WebKit { + +void WebPage::platformInitialize() +{ + notImplemented(); +} + +void WebPage::platformPreferencesDidChange(const WebPreferencesStore&) +{ + notImplemented(); +} + +static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) +{ + page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity); +} + +bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) +{ + if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown) + return false; + + switch (keyboardEvent.windowsVirtualKeyCode()) { + case VK_BACK: + if (keyboardEvent.shiftKey()) + m_page->goForward(); + else + m_page->goBack(); + break; + case VK_SPACE: + scroll(m_page.get(), keyboardEvent.shiftKey() ? ScrollUp : ScrollDown, ScrollByPage); + break; + case VK_LEFT: + scroll(m_page.get(), ScrollLeft, ScrollByLine); + break; + case VK_RIGHT: + scroll(m_page.get(), ScrollRight, ScrollByLine); + break; + case VK_UP: + scroll(m_page.get(), ScrollUp, ScrollByLine); + break; + case VK_DOWN: + scroll(m_page.get(), ScrollDown, ScrollByLine); + break; + case VK_HOME: + scroll(m_page.get(), ScrollUp, ScrollByDocument); + break; + case VK_END: + scroll(m_page.get(), ScrollDown, ScrollByDocument); + break; + case VK_PRIOR: + scroll(m_page.get(), ScrollUp, ScrollByPage); + break; + case VK_NEXT: + scroll(m_page.get(), ScrollDown, ScrollByPage); + break; + default: + return false; + } + + return true; +} + +bool WebPage::platformHasLocalDataForURL(const KURL&) +{ + notImplemented(); + return false; +} + +String WebPage::cachedResponseMIMETypeForURL(const KURL&) +{ + notImplemented(); + return String(); +} + +bool WebPage::platformCanHandleRequest(const ResourceRequest&) +{ + notImplemented(); + return true; +} + +String WebPage::cachedSuggestedFilenameForURL(const KURL&) +{ + notImplemented(); + return String(); +} + +PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&) +{ + notImplemented(); + return 0; +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h b/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h new file mode 100644 index 000000000..92620bec2 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef TiledCoreAnimationDrawingArea_h +#define TiledCoreAnimationDrawingArea_h + +#include "DrawingArea.h" +#include <WebCore/LayerFlushScheduler.h> +#include <WebCore/LayerFlushSchedulerClient.h> +#include <wtf/RetainPtr.h> + +OBJC_CLASS CALayer; +OBJC_CLASS WKContentLayer; + +typedef struct __WKCARemoteLayerClientRef* WKCARemoteLayerClientRef; + +namespace WebKit { + +class TiledCoreAnimationDrawingArea : public DrawingArea, private WebCore::LayerFlushSchedulerClient { +public: + static PassOwnPtr<TiledCoreAnimationDrawingArea> create(WebPage*, const WebPageCreationParameters&); + virtual ~TiledCoreAnimationDrawingArea(); + +private: + TiledCoreAnimationDrawingArea(WebPage*, const WebPageCreationParameters&); + + // DrawingArea + virtual void setNeedsDisplay(const WebCore::IntRect&) OVERRIDE; + virtual void scroll(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) OVERRIDE; + + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) OVERRIDE; + virtual void scheduleCompositingLayerSync() OVERRIDE; + + // WebCore::LayerFlushSchedulerClient + virtual bool flushLayers() OVERRIDE; + + // Message handlers. + virtual void updateGeometry(const WebCore::IntSize& viewSize) OVERRIDE; + + WebCore::LayerFlushScheduler m_layerFlushScheduler; + RetainPtr<WKCARemoteLayerClientRef> m_remoteLayerClient; + + RetainPtr<CALayer> m_rootLayer; +}; + +} // namespace WebKit + +#endif // TiledCoreAnimationDrawingArea_h diff --git a/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm b/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm new file mode 100644 index 000000000..a1da6bde5 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2011 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. + */ + +#import "config.h" +#import "TiledCoreAnimationDrawingArea.h" + +#import "DrawingAreaProxyMessages.h" +#import "EventDispatcher.h" +#import "LayerTreeContext.h" +#import "WebPage.h" +#import "WebProcess.h" +#import <QuartzCore/QuartzCore.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameView.h> +#import <WebCore/GraphicsContext.h> +#import <WebCore/Page.h> +#import <WebCore/ScrollingCoordinator.h> +#import <WebCore/Settings.h> +#import <WebKitSystemInterface.h> + +@interface CATransaction (Details) ++ (void)synchronize; +@end + +using namespace WebCore; + +namespace WebKit { + +PassOwnPtr<TiledCoreAnimationDrawingArea> TiledCoreAnimationDrawingArea::create(WebPage* webPage, const WebPageCreationParameters& parameters) +{ + return adoptPtr(new TiledCoreAnimationDrawingArea(webPage, parameters)); +} + +TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea(WebPage* webPage, const WebPageCreationParameters& parameters) + : DrawingArea(DrawingAreaTypeTiledCoreAnimation, webPage) + , m_layerFlushScheduler(this) +{ + Page* page = webPage->corePage(); + + // FIXME: It's weird that we're mucking around with the settings here. + page->settings()->setForceCompositingMode(true); + +#if ENABLE(THREADED_SCROLLING) + page->settings()->setScrollingCoordinatorEnabled(true); + + WebProcess::shared().eventDispatcher().addScrollingCoordinatorForPage(webPage); +#endif + + m_rootLayer = [CALayer layer]; + + CGRect rootLayerFrame = m_webPage->bounds(); + m_rootLayer.get().frame = rootLayerFrame; + m_rootLayer.get().opaque = YES; + m_rootLayer.get().geometryFlipped = YES; + + mach_port_t serverPort = WebProcess::shared().compositingRenderServerPort(); + m_remoteLayerClient = WKCARemoteLayerClientMakeWithServerPort(serverPort); + WKCARemoteLayerClientSetLayer(m_remoteLayerClient.get(), m_rootLayer.get()); + + LayerTreeContext layerTreeContext; + layerTreeContext.contextID = WKCARemoteLayerClientGetClientId(m_remoteLayerClient.get()); + m_webPage->send(Messages::DrawingAreaProxy::EnterAcceleratedCompositingMode(0, layerTreeContext)); +} + +TiledCoreAnimationDrawingArea::~TiledCoreAnimationDrawingArea() +{ +#if ENABLE(THREADED_SCROLLING) + WebProcess::shared().eventDispatcher().removeScrollingCoordinatorForPage(m_webPage); +#endif + + m_layerFlushScheduler.invalidate(); +} + +void TiledCoreAnimationDrawingArea::setNeedsDisplay(const IntRect& rect) +{ +} + +void TiledCoreAnimationDrawingArea::scroll(const IntRect& scrollRect, const IntSize& scrollOffset) +{ +} + +void TiledCoreAnimationDrawingArea::setRootCompositingLayer(GraphicsLayer* graphicsLayer) +{ + if (!graphicsLayer) { + m_rootLayer.get().sublayers = nil; + return; + } + + m_rootLayer.get().sublayers = [NSArray arrayWithObject:graphicsLayer->platformLayer()]; +} + +void TiledCoreAnimationDrawingArea::scheduleCompositingLayerSync() +{ + m_layerFlushScheduler.schedule(); + // FIXME: Implement +} + +bool TiledCoreAnimationDrawingArea::flushLayers() +{ + // This gets called outside of the normal event loop so wrap in an autorelease pool + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + m_webPage->layoutIfNeeded(); + + bool returnValue = m_webPage->corePage()->mainFrame()->view()->syncCompositingStateIncludingSubframes(); + + [pool drain]; + return returnValue; +} + + +void TiledCoreAnimationDrawingArea::updateGeometry(const IntSize& viewSize) +{ + m_webPage->setSize(viewSize); + m_webPage->layoutIfNeeded(); + + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + + m_rootLayer.get().frame = CGRectMake(0, 0, viewSize.width(), viewSize.height()); + + [CATransaction commit]; + + [CATransaction flush]; + [CATransaction synchronize]; + + m_webPage->send(Messages::DrawingAreaProxy::DidUpdateGeometry()); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/mac/WKAccessibilityWebPageObject.h b/Source/WebKit2/WebProcess/WebPage/mac/WKAccessibilityWebPageObject.h new file mode 100644 index 000000000..2772ad0e1 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/mac/WKAccessibilityWebPageObject.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef WKAccessibilityWebPageObject_h +#define WKAccessibilityWebPageObject_h + +namespace WebKit { +class WebPage; +} + +@interface WKAccessibilityWebPageObject : NSObject { + WebKit::WebPage* m_page; + + id m_parent; + NSArray* m_attributeNames; + NSMutableArray* m_accessibilityChildren; +} + +- (void)setWebPage:(WebKit::WebPage*)page; + +- (void)setRemoteParent:(id)parent; + +@end + +#endif // WKAccessibilityWebPageObject_h diff --git a/Source/WebKit2/WebProcess/WebPage/mac/WKAccessibilityWebPageObject.mm b/Source/WebKit2/WebProcess/WebPage/mac/WKAccessibilityWebPageObject.mm new file mode 100644 index 000000000..6ed37ea10 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/mac/WKAccessibilityWebPageObject.mm @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2011 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. + */ + +#import "config.h" +#import "WKAccessibilityWebPageObject.h" + +#import "WebFrame.h" +#import "WebPage.h" +#import <WebCore/AXObjectCache.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameView.h> +#import <WebCore/Page.h> +#import <WebCore/ScrollView.h> +#import <WebCore/Scrollbar.h> +#import <WebKitSystemInterface.h> + +using namespace WebCore; +using namespace WebKit; + +@implementation WKAccessibilityWebPageObject + +- (id)accessibilityRootObjectWrapper +{ + WebCore::Page* page = m_page->corePage(); + if (!page) + return nil; + + WebCore::Frame* core = page->mainFrame(); + if (!core || !core->document()) + return nil; + + AccessibilityObject* root = core->document()->axObjectCache()->rootObject(); + if (!root) + return nil; + + return root->wrapper(); +} + +- (void)setWebPage:(WebPage*)page +{ + m_page = page; +} + +- (void)setRemoteParent:(id)parent +{ + if (parent != m_parent) { + [m_parent release]; + m_parent = [parent retain]; + } +} + +- (void)dealloc +{ + WKUnregisterUniqueIdForElement(self); + [m_accessibilityChildren release]; + [m_attributeNames release]; + [m_parent release]; + [super dealloc]; +} + +- (BOOL)accessibilityIsIgnored +{ + return NO; +} + +- (NSArray *)accessibilityAttributeNames +{ + if (!m_attributeNames) + m_attributeNames = [[NSArray alloc] initWithObjects: + NSAccessibilityRoleAttribute, NSAccessibilityRoleDescriptionAttribute, NSAccessibilityFocusedAttribute, + NSAccessibilityParentAttribute, NSAccessibilityWindowAttribute, NSAccessibilityTopLevelUIElementAttribute, + NSAccessibilityPositionAttribute, NSAccessibilitySizeAttribute, NSAccessibilityChildrenAttribute, nil]; + + return m_attributeNames; +} + +- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute +{ + return NO; +} + +- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute +{ + return; +} + +- (NSArray *)accessibilityActionNames +{ + return [NSArray array]; +} + +- (NSArray *)accessibilityChildren +{ + id wrapper = [self accessibilityRootObjectWrapper]; + if (!wrapper) + return [NSArray array]; + + return [NSArray arrayWithObject:wrapper]; +} + +- (id)accessibilityAttributeValue:(NSString *)attribute +{ + if (!WebCore::AXObjectCache::accessibilityEnabled()) + WebCore::AXObjectCache::enableAccessibility(); + + if ([attribute isEqualToString:NSAccessibilityParentAttribute]) + return m_parent; + if ([attribute isEqualToString:NSAccessibilityWindowAttribute]) + return [m_parent accessibilityAttributeValue:NSAccessibilityWindowAttribute]; + if ([attribute isEqualToString:NSAccessibilityTopLevelUIElementAttribute]) + return [m_parent accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) + return NSAccessibilityGroupRole; + if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) + return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, nil); + if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) + return [NSNumber numberWithBool:NO]; + + if (!m_page) + return nil; + + if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) { + WebCore::IntPoint point = m_page->accessibilityPosition(); + return [NSValue valueWithPoint:NSMakePoint(point.x(), point.y())]; + } + if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) { + const IntSize& s = m_page->size(); + return [NSValue valueWithSize:NSMakeSize(s.width(), s.height())]; + } + if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) + return [self accessibilityChildren]; + + return nil; +} + +- (BOOL)accessibilityShouldUseUniqueId +{ + return YES; +} + +- (id)accessibilityHitTest:(NSPoint)point +{ + // Hit-test point comes in as bottom-screen coordinates. Needs to be normalized to the frame of the web page. + NSPoint remotePosition = [[self accessibilityAttributeValue:NSAccessibilityPositionAttribute] pointValue]; + NSSize remoteSize = [[self accessibilityAttributeValue:NSAccessibilitySizeAttribute] sizeValue]; + + // Get the y position of the WKView (we have to screen-flip and go from bottom left to top left). + CGFloat screenHeight = [(NSScreen *)[[NSScreen screens] objectAtIndex:0] frame].size.height; + remotePosition.y = (screenHeight - remotePosition.y) - remoteSize.height; + + point.y = screenHeight - point.y; + + // Re-center point into the web page's frame. + point.y -= remotePosition.y; + point.x -= remotePosition.x; + + WebCore::FrameView* frameView = m_page ? m_page->mainFrameView() : 0; + if (frameView) { + point.y += frameView->scrollPosition().y(); + point.x += frameView->scrollPosition().x(); + } + + return [[self accessibilityRootObjectWrapper] accessibilityHitTest:point]; +} + +- (id)accessibilityFocusedUIElement +{ + return [[self accessibilityRootObjectWrapper] accessibilityFocusedUIElement]; +} + + +@end diff --git a/Source/WebKit2/WebProcess/WebPage/mac/WebInspectorMac.mm b/Source/WebKit2/WebProcess/WebPage/mac/WebInspectorMac.mm new file mode 100644 index 000000000..d64bf9cf5 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/mac/WebInspectorMac.mm @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#import "config.h" +#import "WebInspector.h" + +#import <wtf/text/WTFString.h> + +namespace WebKit { + +static String& globalInspectorLocalizedStringsURL() +{ + DEFINE_STATIC_LOCAL(String, inspectorLocalizedStringsURL, ()); + return inspectorLocalizedStringsURL; +} + +void WebInspector::setLocalizedStringsPath(const String& path) +{ + if (!path.isEmpty()) + globalInspectorLocalizedStringsURL() = [[NSURL fileURLWithPath:path] absoluteString]; + else + globalInspectorLocalizedStringsURL() = String(); +} + +String WebInspector::localizedStringsURL() const +{ + return globalInspectorLocalizedStringsURL(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm b/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm new file mode 100644 index 000000000..bfee90207 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm @@ -0,0 +1,710 @@ +/* + * Copyright (C) 2010, 2011 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. + */ + +#import "config.h" +#import "WebPage.h" + +#import "AttributedString.h" +#import "DataReference.h" +#import "EditorState.h" +#import "PluginView.h" +#import "WKAccessibilityWebPageObject.h" +#import "WebCoreArgumentCoders.h" +#import "WebEvent.h" +#import "WebEventConversion.h" +#import "WebFrame.h" +#import "WebPageProxyMessages.h" +#import "WebProcess.h" +#import <WebCore/AXObjectCache.h> +#import <WebCore/FocusController.h> +#import <WebCore/Frame.h> +#import <WebCore/FrameView.h> +#import <WebCore/HitTestResult.h> +#import <WebCore/HTMLConverter.h> +#import <WebCore/KeyboardEvent.h> +#import <WebCore/Page.h> +#import <WebCore/PlatformKeyboardEvent.h> +#import <WebCore/ResourceHandle.h> +#import <WebCore/RenderObject.h> +#import <WebCore/RenderStyle.h> +#import <WebCore/ScrollView.h> +#import <WebCore/TextIterator.h> +#import <WebCore/WindowsKeyboardCodes.h> +#import <WebCore/visible_units.h> +#import <WebKitSystemInterface.h> + +using namespace WebCore; + +namespace WebKit { + +static PassRefPtr<Range> convertToRange(Frame*, NSRange); + +void WebPage::platformInitialize() +{ +#if USE(CFNETWORK) + m_page->addSchedulePair(SchedulePair::create([[NSRunLoop currentRunLoop] getCFRunLoop], kCFRunLoopCommonModes)); +#else + m_page->addSchedulePair(SchedulePair::create([NSRunLoop currentRunLoop], kCFRunLoopCommonModes)); +#endif + + WKAccessibilityWebPageObject* mockAccessibilityElement = [[[WKAccessibilityWebPageObject alloc] init] autorelease]; + + // Get the pid for the starting process. + pid_t pid = WebProcess::shared().presenterApplicationPid(); + WKAXInitializeElementWithPresenterPid(mockAccessibilityElement, pid); + [mockAccessibilityElement setWebPage:this]; + + // send data back over + NSData* remoteToken = (NSData *)WKAXRemoteTokenForElement(mockAccessibilityElement); + CoreIPC::DataReference dataToken = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>([remoteToken bytes]), [remoteToken length]); + send(Messages::WebPageProxy::RegisterWebProcessAccessibilityToken(dataToken)); + m_mockAccessibilityElement = mockAccessibilityElement; +} + +void WebPage::platformPreferencesDidChange(const WebPreferencesStore&) +{ +} + +typedef HashMap<String, String> SelectorNameMap; + +// Map selectors into Editor command names. +// This is not needed for any selectors that have the same name as the Editor command. +static const SelectorNameMap* createSelectorExceptionMap() +{ + SelectorNameMap* map = new HashMap<String, String>; + + map->add("insertNewlineIgnoringFieldEditor:", "InsertNewline"); + map->add("insertParagraphSeparator:", "InsertNewline"); + map->add("insertTabIgnoringFieldEditor:", "InsertTab"); + map->add("pageDown:", "MovePageDown"); + map->add("pageDownAndModifySelection:", "MovePageDownAndModifySelection"); + map->add("pageUp:", "MovePageUp"); + map->add("pageUpAndModifySelection:", "MovePageUpAndModifySelection"); + + return map; +} + +static String commandNameForSelectorName(const String& selectorName) +{ + // Check the exception map first. + static const SelectorNameMap* exceptionMap = createSelectorExceptionMap(); + SelectorNameMap::const_iterator it = exceptionMap->find(selectorName); + if (it != exceptionMap->end()) + return it->second; + + // Remove the trailing colon. + // No need to capitalize the command name since Editor command names are not case sensitive. + size_t selectorNameLength = selectorName.length(); + if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':') + return String(); + return selectorName.left(selectorNameLength - 1); +} + +static Frame* frameForEvent(KeyboardEvent* event) +{ + Node* node = event->target()->toNode(); + ASSERT(node); + Frame* frame = node->document()->frame(); + ASSERT(frame); + return frame; +} + +bool WebPage::executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>& commands, KeyboardEvent* event) +{ + Frame* frame = frameForEvent(event); + ASSERT(frame->page() == corePage()); + + bool eventWasHandled = false; + for (size_t i = 0; i < commands.size(); ++i) { + if (commands[i].commandName == "insertText:") { + ASSERT(!frame->editor()->hasComposition()); + + if (!frame->editor()->canEdit()) + continue; + + // An insertText: might be handled by other responders in the chain if we don't handle it. + // One example is space bar that results in scrolling down the page. + eventWasHandled |= frame->editor()->insertText(commands[i].text, event); + } else { + Editor::Command command = frame->editor()->command(commandNameForSelectorName(commands[i].commandName)); + if (command.isSupported()) { + bool commandExecutedByEditor = command.execute(event); + eventWasHandled |= commandExecutedByEditor; + if (!commandExecutedByEditor) { + bool performedNonEditingBehavior = event->keyEvent()->type() == PlatformEvent::RawKeyDown && performNonEditingBehaviorForSelector(commands[i].commandName); + eventWasHandled |= performedNonEditingBehavior; + } + } else { + bool commandWasHandledByUIProcess = false; + WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::ExecuteSavedCommandBySelector(commands[i].commandName), + Messages::WebPageProxy::ExecuteSavedCommandBySelector::Reply(commandWasHandledByUIProcess), m_pageID); + eventWasHandled |= commandWasHandledByUIProcess; + } + } + } + return eventWasHandled; +} + +bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* event, bool saveCommands) +{ + ASSERT(!saveCommands || event->keypressCommands().isEmpty()); // Save commands once for each event. + + Frame* frame = frameForEvent(event); + + const PlatformKeyboardEvent* platformEvent = event->keyEvent(); + if (!platformEvent) + return false; + Vector<KeypressCommand>& commands = event->keypressCommands(); + + if ([platformEvent->macEvent() type] == NSFlagsChanged) + return false; + + bool eventWasHandled = false; + + if (saveCommands) { + KeyboardEvent* oldEvent = m_keyboardEventBeingInterpreted; + m_keyboardEventBeingInterpreted = event; + bool sendResult = WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretQueuedKeyEvent(editorState()), + Messages::WebPageProxy::InterpretQueuedKeyEvent::Reply(eventWasHandled, commands), m_pageID); + m_keyboardEventBeingInterpreted = oldEvent; + if (!sendResult) + return false; + + // An input method may make several actions per keypress. For example, pressing Return with Korean IM both confirms it and sends a newline. + // IM-like actions are handled immediately (so the return value from UI process is true), but there are saved commands that + // should be handled like normal text input after DOM event dispatch. + if (!event->keypressCommands().isEmpty()) + return false; + } else { + // Are there commands that could just cause text insertion if executed via Editor? + // WebKit doesn't have enough information about mode to decide how they 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). + bool haveTextInsertionCommands = false; + for (size_t i = 0; i < commands.size(); ++i) { + if (frame->editor()->command(commandNameForSelectorName(commands[i].commandName)).isTextInsertion()) + haveTextInsertionCommands = true; + } + // If there are no text insertion commands, default keydown handler is the right time to execute the commands. + // Keypress (Char event) handler is the latest opportunity to execute. + if (!haveTextInsertionCommands || platformEvent->type() == PlatformEvent::Char) { + eventWasHandled = executeKeypressCommandsInternal(event->keypressCommands(), event); + event->keypressCommands().clear(); + } + } + return eventWasHandled; +} + +void WebPage::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput) +{ + for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) { + if ((*it)->sendComplexTextInput(pluginComplexTextInputIdentifier, textInput)) + break; + } +} + +void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + if (frame->selection()->isContentEditable()) { + RefPtr<Range> replacementRange; + if (replacementRangeStart != NSNotFound) { + replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart)); + frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); + } + + frame->editor()->setComposition(text, underlines, selectionStart, selectionEnd); + } + + newState = editorState(); +} + +void WebPage::confirmComposition(EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + frame->editor()->confirmComposition(); + + newState = editorState(); +} + +void WebPage::cancelComposition(EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + frame->editor()->cancelComposition(); + + newState = editorState(); +} + +void WebPage::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, bool& handled, EditorState& newState) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + RefPtr<Range> replacementRange; + if (replacementRangeStart != NSNotFound) { + replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart)); + frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); + } + + if (!frame->editor()->hasComposition()) { + // An insertText: might be handled by other responders in the chain if we don't handle it. + // One example is space bar that results in scrolling down the page. + handled = frame->editor()->insertText(text, m_keyboardEventBeingInterpreted); + } else { + handled = true; + frame->editor()->confirmComposition(text); + } + + newState = editorState(); +} + +void WebPage::getMarkedRange(uint64_t& location, uint64_t& length) +{ + location = NSNotFound; + length = 0; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + RefPtr<Range> range = frame->editor()->compositionRange(); + size_t locationSize; + size_t lengthSize; + if (range && TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), locationSize, lengthSize)) { + location = static_cast<uint64_t>(locationSize); + length = static_cast<uint64_t>(lengthSize); + } +} + +void WebPage::getSelectedRange(uint64_t& location, uint64_t& length) +{ + location = NSNotFound; + length = 0; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + size_t locationSize; + size_t lengthSize; + RefPtr<Range> range = frame->selection()->toNormalizedRange(); + if (range && TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), locationSize, lengthSize)) { + location = static_cast<uint64_t>(locationSize); + length = static_cast<uint64_t>(lengthSize); + } +} + +void WebPage::getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString& result) +{ + NSRange nsRange = NSMakeRange(location, length - location); + + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + if (frame->selection()->isNone() || !frame->selection()->isContentEditable() || frame->selection()->isInPasswordField()) + return; + + RefPtr<Range> range = convertToRange(frame, nsRange); + if (!range) + return; + + result.string = [WebHTMLConverter editingAttributedStringFromRange:range.get()]; + NSAttributedString* attributedString = result.string.get(); + + // [WebHTMLConverter editingAttributedStringFromRange:] insists on inserting a trailing + // whitespace at the end of the string which breaks the ATOK input method. <rdar://problem/5400551> + // To work around this we truncate the resultant string to the correct length. + if ([attributedString length] > nsRange.length) { + ASSERT([attributedString length] == nsRange.length + 1); + ASSERT([[attributedString string] characterAtIndex:nsRange.length] == '\n' || [[attributedString string] characterAtIndex:nsRange.length] == ' '); + result.string = [attributedString attributedSubstringFromRange:NSMakeRange(0, nsRange.length)]; + } +} + +void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index) +{ + index = NSNotFound; + Frame* frame = m_page->mainFrame(); + if (!frame) + return; + + HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(point, false); + frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame(); + + RefPtr<Range> range = frame->rangeForPoint(result.point()); + if (!range) + return; + + size_t location; + size_t length; + if (TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), location, length)) + index = static_cast<uint64_t>(location); +} + +PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange) +{ + if (nsrange.location > INT_MAX) + return 0; + if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX) + nsrange.length = INT_MAX - nsrange.location; + + // our critical assumption is that we are only called by input methods that + // concentrate on a given area containing the selection + // We have to do this because of text fields and textareas. The DOM for those is not + // directly in the document DOM, so serialization is problematic. Our solution is + // to use the root editable element of the selection start as the positional base. + // That fits with AppKit's idea of an input context. + return TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), nsrange.location, nsrange.length); +} + +void WebPage::firstRectForCharacterRange(uint64_t location, uint64_t length, WebCore::IntRect& resultRect) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + resultRect.setLocation(IntPoint(0, 0)); + resultRect.setSize(IntSize(0, 0)); + + RefPtr<Range> range = convertToRange(frame, NSMakeRange(location, length)); + if (!range) + return; + + ASSERT(range->startContainer()); + ASSERT(range->endContainer()); + + IntRect rect = frame->editor()->firstRectForRange(range.get()); + resultRect = frame->view()->contentsToWindow(rect); +} + +void WebPage::executeKeypressCommands(const Vector<WebCore::KeypressCommand>& commands, bool& handled, EditorState& newState) +{ + handled = executeKeypressCommandsInternal(commands, m_keyboardEventBeingInterpreted); + newState = editorState(); +} + +static bool isPositionInRange(const VisiblePosition& position, Range* range) +{ + RefPtr<Range> positionRange = makeRange(position, position); + + ExceptionCode ec = 0; + range->compareBoundaryPoints(Range::START_TO_START, positionRange.get(), ec); + if (ec) + return false; + + if (!range->isPointInRange(positionRange->startContainer(), positionRange->startOffset(), ec)) + return false; + if (ec) + return false; + + return true; +} + +static bool shouldUseSelection(const VisiblePosition& position, const VisibleSelection& selection) +{ + if (!selection.isRange()) + return false; + + RefPtr<Range> selectedRange = selection.toNormalizedRange(); + if (!selectedRange) + return false; + + return isPositionInRange(position, selectedRange.get()); +} + +void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint) +{ + Frame* frame = m_page->mainFrame(); + if (!frame) + return; + + // Find the frame the point is over. + IntPoint point = roundedIntPoint(floatPoint); + HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(point, false); + frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame(); + + IntPoint translatedPoint = frame->view()->windowToContents(point); + + // Don't do anything if there is no character at the point. + if (!frame->rangeForPoint(translatedPoint)) + return; + + VisiblePosition position = frame->visiblePositionForPoint(translatedPoint); + VisibleSelection selection = m_page->focusController()->focusedOrMainFrame()->selection()->selection(); + if (shouldUseSelection(position, selection)) { + performDictionaryLookupForSelection(DictionaryPopupInfo::HotKey, frame, selection); + return; + } + + NSDictionary *options = nil; + +#if !defined(BUILDING_ON_SNOW_LEOPARD) + // As context, we are going to use the surrounding paragraph of text. + VisiblePosition paragraphStart = startOfParagraph(position); + VisiblePosition paragraphEnd = endOfParagraph(position); + + NSRange rangeToPass = NSMakeRange(TextIterator::rangeLength(makeRange(paragraphStart, position).get()), 0); + + RefPtr<Range> fullCharacterRange = makeRange(paragraphStart, paragraphEnd); + String fullPlainTextString = plainText(fullCharacterRange.get()); + + NSRange extractedRange = WKExtractWordDefinitionTokenRangeFromContextualString(fullPlainTextString, rangeToPass, &options); + + RefPtr<Range> finalRange = TextIterator::subrange(fullCharacterRange.get(), extractedRange.location, extractedRange.length); + if (!finalRange) + return; +#else + RefPtr<Range> finalRange = makeRange(startOfWord(position), endOfWord(position)); + if (!finalRange) + return; +#endif + + performDictionaryLookupForRange(DictionaryPopupInfo::HotKey, frame, finalRange.get(), options); +} + +void WebPage::performDictionaryLookupForSelection(DictionaryPopupInfo::Type type, Frame* frame, const VisibleSelection& selection) +{ + RefPtr<Range> selectedRange = selection.toNormalizedRange(); + if (!selectedRange) + return; + + NSDictionary *options = nil; + +#if !defined(BUILDING_ON_SNOW_LEOPARD) + VisiblePosition selectionStart = selection.visibleStart(); + VisiblePosition selectionEnd = selection.visibleEnd(); + + // As context, we are going to use the surrounding paragraphs of text. + VisiblePosition paragraphStart = startOfParagraph(selectionStart); + VisiblePosition paragraphEnd = endOfParagraph(selectionEnd); + + int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get()); + int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get()); + NSRange rangeToPass = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart); + + String fullPlainTextString = plainText(makeRange(paragraphStart, paragraphEnd).get()); + + // Since we already have the range we want, we just need to grab the returned options. + WKExtractWordDefinitionTokenRangeFromContextualString(fullPlainTextString, rangeToPass, &options); +#endif + + performDictionaryLookupForRange(type, frame, selectedRange.get(), options); +} + +void WebPage::performDictionaryLookupForRange(DictionaryPopupInfo::Type type, Frame* frame, Range* range, NSDictionary *options) +{ + String rangeText = range->text(); + if (rangeText.stripWhiteSpace().isEmpty()) + return; + + RenderObject* renderer = range->startContainer()->renderer(); + RenderStyle* style = renderer->style(); + NSFont *font = style->font().primaryFont()->getNSFont(); + + // We won't be able to get an NSFont in the case that a Web Font is being used, so use + // the default system font at the same size instead. + if (!font) + font = [NSFont systemFontOfSize:style->font().primaryFont()->platformData().size()]; + + CFDictionaryRef fontDescriptorAttributes = (CFDictionaryRef)[[font fontDescriptor] fontAttributes]; + if (!fontDescriptorAttributes) + return; + + Vector<FloatQuad> quads; + range->textQuads(quads); + if (quads.isEmpty()) + return; + + IntRect rangeRect = frame->view()->contentsToWindow(quads[0].enclosingBoundingBox()); + + DictionaryPopupInfo dictionaryPopupInfo; + dictionaryPopupInfo.type = type; + dictionaryPopupInfo.origin = FloatPoint(rangeRect.x(), rangeRect.y() + style->fontMetrics().ascent()); + dictionaryPopupInfo.fontInfo.fontAttributeDictionary = fontDescriptorAttributes; +#if !defined(BUILDING_ON_SNOW_LEOPARD) + dictionaryPopupInfo.options = (CFDictionaryRef)options; +#endif + + send(Messages::WebPageProxy::DidPerformDictionaryLookup(rangeText, dictionaryPopupInfo)); +} + +bool WebPage::performNonEditingBehaviorForSelector(const String& selector) +{ + // FIXME: All these selectors have corresponding Editor commands, but the commands only work in editable content. + // Should such non-editing behaviors be implemented in Editor or EventHandler::defaultArrowEventHandler() perhaps? + if (selector == "moveUp:") + scroll(m_page.get(), ScrollUp, ScrollByLine); + else if (selector == "moveToBeginningOfParagraph:") + scroll(m_page.get(), ScrollUp, ScrollByPage); + else if (selector == "moveToBeginningOfDocument:") { + scroll(m_page.get(), ScrollUp, ScrollByDocument); + scroll(m_page.get(), ScrollLeft, ScrollByDocument); + } else if (selector == "moveDown:") + scroll(m_page.get(), ScrollDown, ScrollByLine); + else if (selector == "moveToEndOfParagraph:") + scroll(m_page.get(), ScrollDown, ScrollByPage); + else if (selector == "moveToEndOfDocument:") { + scroll(m_page.get(), ScrollDown, ScrollByDocument); + scroll(m_page.get(), ScrollLeft, ScrollByDocument); + } else if (selector == "moveLeft:") + scroll(m_page.get(), ScrollLeft, ScrollByLine); + else if (selector == "moveWordLeft:") + scroll(m_page.get(), ScrollLeft, ScrollByPage); + else if (selector == "moveToLeftEndOfLine:") + m_page->goBack(); + else if (selector == "moveRight:") + scroll(m_page.get(), ScrollRight, ScrollByLine); + else if (selector == "moveWordRight:") + scroll(m_page.get(), ScrollRight, ScrollByPage); + else if (selector == "moveToRightEndOfLine:") + m_page->goForward(); + else + return false; + + return true; +} + +bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&) +{ + return false; +} + +void WebPage::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elementToken, const CoreIPC::DataReference& windowToken) +{ + NSData* elementTokenData = [NSData dataWithBytes:elementToken.data() length:elementToken.size()]; + NSData* windowTokenData = [NSData dataWithBytes:windowToken.data() length:windowToken.size()]; + id remoteElement = WKAXRemoteElementForToken(elementTokenData); + id remoteWindow = WKAXRemoteElementForToken(windowTokenData); + WKAXSetWindowForRemoteElement(remoteWindow, remoteElement); + + [accessibilityRemoteObject() setRemoteParent:remoteElement]; +} + +void WebPage::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes, bool& result) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || frame->selection()->isNone()) { + result = false; + return; + } + frame->editor()->writeSelectionToPasteboard(pasteboardName, pasteboardTypes); + result = true; +} + +void WebPage::readSelectionFromPasteboard(const String& pasteboardName, bool& result) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || frame->selection()->isNone()) { + result = false; + return; + } + frame->editor()->readSelectionFromPasteboard(pasteboardName); + result = true; +} + +WKAccessibilityWebPageObject* WebPage::accessibilityRemoteObject() +{ + return m_mockAccessibilityElement.get(); +} + +bool WebPage::platformHasLocalDataForURL(const WebCore::KURL& url) +{ + NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url]; + [request setValue:(NSString*)userAgent() forHTTPHeaderField:@"User-Agent"]; + NSCachedURLResponse *cachedResponse; +#if USE(CFURLSTORAGESESSIONS) + if (CFURLStorageSessionRef storageSession = ResourceHandle::currentStorageSession()) + cachedResponse = WKCachedResponseForRequest(storageSession, request); + else +#endif + cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request]; + [request release]; + + return cachedResponse; +} + +static NSCachedURLResponse *cachedResponseForURL(WebPage* webPage, const KURL& url) +{ + RetainPtr<NSMutableURLRequest> request(AdoptNS, [[NSMutableURLRequest alloc] initWithURL:url]); + [request.get() setValue:(NSString *)webPage->userAgent() forHTTPHeaderField:@"User-Agent"]; + +#if USE(CFURLSTORAGESESSIONS) + if (CFURLStorageSessionRef storageSession = ResourceHandle::currentStorageSession()) + return WKCachedResponseForRequest(storageSession, request.get()); +#endif + + return [[NSURLCache sharedURLCache] cachedResponseForRequest:request.get()]; +} + +String WebPage::cachedSuggestedFilenameForURL(const KURL& url) +{ + return [[cachedResponseForURL(this, url) response] suggestedFilename]; +} + +String WebPage::cachedResponseMIMETypeForURL(const KURL& url) +{ + return [[cachedResponseForURL(this, url) response] MIMEType]; +} + +PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL& url) +{ + return SharedBuffer::wrapNSData([cachedResponseForURL(this, url) data]); +} + +bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request) +{ + if ([NSURLConnection canHandleRequest:request.nsURLRequest()]) + return true; + + // FIXME: Return true if this scheme is any one WebKit2 knows how to handle. + return request.url().protocolIs("applewebdata"); +} + +void WebPage::shouldDelayWindowOrderingEvent(const WebKit::WebMouseEvent& event, bool& result) +{ + result = false; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true); + if (hitResult.isSelected()) + result = frame->eventHandler()->eventMayStartDrag(platform(event)); +} + +void WebPage::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event, bool& result) +{ + result = false; + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true); + frame->eventHandler()->setActivationEventNumber(eventNumber); + if (hitResult.isSelected()) + result = frame->eventHandler()->eventMayStartDrag(platform(event)); + else + result = !!hitResult.scrollbar(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.cpp b/Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.cpp new file mode 100644 index 000000000..266a3a95d --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.cpp @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * 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 "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "LayerTreeHostQt.h" + +#include "DrawingAreaImpl.h" +#include "GraphicsContext.h" +#include "LayerTreeHostProxyMessages.h" +#include "MessageID.h" +#include "WebGraphicsLayer.h" +#include "WebPage.h" +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/Page.h> +#include <WebCore/Settings.h> + +using namespace WebCore; + +namespace WebKit { + +PassRefPtr<LayerTreeHostQt> LayerTreeHostQt::create(WebPage* webPage) +{ + return adoptRef(new LayerTreeHostQt(webPage)); +} + +LayerTreeHostQt::~LayerTreeHostQt() +{ +} + +LayerTreeHostQt::LayerTreeHostQt(WebPage* webPage) + : LayerTreeHost(webPage) + , m_notifyAfterScheduledLayerFlush(false) + , m_isValid(true) +#if USE(TILED_BACKING_STORE) + , m_waitingForUIProcess(false) + , m_isSuspended(false) +#endif + , m_shouldSyncFrame(false) + , m_shouldSyncRootLayer(true) + , m_layerFlushTimer(this, &LayerTreeHostQt::layerFlushTimerFired) + , m_layerFlushSchedulingEnabled(true) + , m_shouldRecreateBackingStore(false) +{ + // Create a root layer. + m_rootLayer = GraphicsLayer::create(this); + WebGraphicsLayer* webRootLayer = toWebGraphicsLayer(m_rootLayer.get()); + webRootLayer->setRootLayer(true); +#ifndef NDEBUG + m_rootLayer->setName("LayerTreeHostQt root layer"); +#endif + m_rootLayer->setDrawsContent(false); + m_rootLayer->setSize(m_webPage->size()); + m_layerTreeContext.webLayerID = toWebGraphicsLayer(webRootLayer)->id(); + + m_nonCompositedContentLayer = GraphicsLayer::create(this); +#if USE(TILED_BACKING_STORE) + toWebGraphicsLayer(m_rootLayer.get())->setLayerTreeTileClient(this); +#endif +#ifndef NDEBUG + m_nonCompositedContentLayer->setName("LayerTreeHostQt non-composited content"); +#endif + m_nonCompositedContentLayer->setDrawsContent(true); + m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground()); + m_nonCompositedContentLayer->setSize(m_webPage->size()); + + m_rootLayer->addChild(m_nonCompositedContentLayer.get()); + + if (m_webPage->hasPageOverlay()) + createPageOverlayLayer(); + + scheduleLayerFlush(); +} + +void LayerTreeHostQt::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled) +{ + if (m_layerFlushSchedulingEnabled == layerFlushingEnabled) + return; + + m_layerFlushSchedulingEnabled = layerFlushingEnabled; + + if (m_layerFlushSchedulingEnabled) { + scheduleLayerFlush(); + return; + } + + cancelPendingLayerFlush(); +} + +void LayerTreeHostQt::scheduleLayerFlush() +{ + if (!m_layerFlushSchedulingEnabled) + return; + + if (!m_layerFlushTimer.isActive()) + m_layerFlushTimer.startOneShot(0); +} + +void LayerTreeHostQt::cancelPendingLayerFlush() +{ + m_layerFlushTimer.stop(); +} + +void LayerTreeHostQt::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush) +{ + m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush; +} + +void LayerTreeHostQt::setRootCompositingLayer(WebCore::GraphicsLayer* graphicsLayer) +{ + m_nonCompositedContentLayer->removeAllChildren(); + + // Add the accelerated layer tree hierarchy. + if (graphicsLayer) + m_nonCompositedContentLayer->addChild(graphicsLayer); +} + +void LayerTreeHostQt::invalidate() +{ + cancelPendingLayerFlush(); + + ASSERT(m_isValid); + m_rootLayer = nullptr; + m_isValid = false; +} + +void LayerTreeHostQt::setNonCompositedContentsNeedDisplay(const WebCore::IntRect& rect) +{ + m_nonCompositedContentLayer->setNeedsDisplayInRect(rect); + if (m_pageOverlayLayer) + m_pageOverlayLayer->setNeedsDisplayInRect(rect); + + scheduleLayerFlush(); +} + +void LayerTreeHostQt::scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset) +{ + setNonCompositedContentsNeedDisplay(scrollRect); +} + +void LayerTreeHostQt::forceRepaint() +{ + scheduleLayerFlush(); +} + +void LayerTreeHostQt::sizeDidChange(const WebCore::IntSize& newSize) +{ + m_rootLayer->setSize(newSize); + + // If the newSize exposes new areas of the non-composited content a setNeedsDisplay is needed + // for those newly exposed areas. + FloatSize oldSize = m_nonCompositedContentLayer->size(); + m_nonCompositedContentLayer->setSize(newSize); + + if (newSize.width() > oldSize.width()) { + float height = std::min(static_cast<float>(newSize.height()), oldSize.height()); + m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(oldSize.width(), 0, newSize.width() - oldSize.width(), height)); + } + + if (newSize.height() > oldSize.height()) + m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height())); + + if (m_pageOverlayLayer) + m_pageOverlayLayer->setSize(newSize); + + scheduleLayerFlush(); +} + +void LayerTreeHostQt::didInstallPageOverlay() +{ + createPageOverlayLayer(); + scheduleLayerFlush(); +} + +void LayerTreeHostQt::didUninstallPageOverlay() +{ + destroyPageOverlayLayer(); + scheduleLayerFlush(); +} + +void LayerTreeHostQt::setPageOverlayNeedsDisplay(const WebCore::IntRect& rect) +{ + ASSERT(m_pageOverlayLayer); + m_pageOverlayLayer->setNeedsDisplayInRect(rect); + scheduleLayerFlush(); +} + +bool LayerTreeHostQt::flushPendingLayerChanges() +{ + recreateBackingStoreIfNeeded(); + + bool didSync = m_webPage->corePage()->mainFrame()->view()->syncCompositingStateIncludingSubframes(); + m_nonCompositedContentLayer->syncCompositingStateForThisLayerOnly(); + if (m_pageOverlayLayer) + m_pageOverlayLayer->syncCompositingStateForThisLayerOnly(); + + m_rootLayer->syncCompositingStateForThisLayerOnly(); + return didSync; +} + +void LayerTreeHostQt::didSyncCompositingStateForLayer(const WebLayerInfo& info) +{ + m_shouldSyncFrame = true; + m_webPage->send(Messages::LayerTreeHostProxy::SyncCompositingLayerState(info)); +} + +void LayerTreeHostQt::didDeleteLayer(WebLayerID id) +{ + m_shouldSyncFrame = true; + m_webPage->send(Messages::LayerTreeHostProxy::DeleteCompositingLayer(id)); +} + +void LayerTreeHostQt::performScheduledLayerFlush() +{ + m_webPage->layoutIfNeeded(); + + if (!m_isValid) + return; + +#if USE(TILED_BACKING_STORE) + if (m_isSuspended || m_waitingForUIProcess) + return; +#endif + + m_shouldSyncFrame = false; + flushPendingLayerChanges(); + if (!m_shouldSyncFrame) + return; + + if (m_shouldSyncRootLayer) { + m_webPage->send(Messages::LayerTreeHostProxy::SetRootCompositingLayer(toWebGraphicsLayer(m_rootLayer.get())->id())); + m_shouldSyncRootLayer = false; + } + + m_webPage->send(Messages::LayerTreeHostProxy::DidRenderFrame()); + + if (!m_notifyAfterScheduledLayerFlush) + return; + + // Let the drawing area know that we've done a flush of the layer changes. + static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers(); + m_notifyAfterScheduledLayerFlush = false; +} + +void LayerTreeHostQt::layerFlushTimerFired(Timer<LayerTreeHostQt>*) +{ + performScheduledLayerFlush(); +} + +void LayerTreeHostQt::createPageOverlayLayer() +{ + ASSERT(!m_pageOverlayLayer); + + m_pageOverlayLayer = GraphicsLayer::create(this); +#ifndef NDEBUG + m_pageOverlayLayer->setName("LayerTreeHostQt page overlay content"); +#endif + + m_pageOverlayLayer->setDrawsContent(true); + m_pageOverlayLayer->setSize(m_webPage->size()); + + m_rootLayer->addChild(m_pageOverlayLayer.get()); +} + +void LayerTreeHostQt::destroyPageOverlayLayer() +{ + ASSERT(m_pageOverlayLayer); + m_pageOverlayLayer->removeFromParent(); + m_pageOverlayLayer = nullptr; +} + +int64_t LayerTreeHostQt::adoptImageBackingStore(Image* image) +{ + if (!image) + return InvalidWebLayerID; + QPixmap* pixmap = image->nativeImageForCurrentFrame(); + + if (!pixmap) + return InvalidWebLayerID; + + int64_t key = pixmap->cacheKey(); + HashMap<int64_t, int>::iterator it = m_directlyCompositedImageRefCounts.find(key); + + if (it != m_directlyCompositedImageRefCounts.end()) { + ++(it->second); + return key; + } + + RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(image->size(), image->currentFrameHasAlpha() ? ShareableBitmap::SupportsAlpha : 0); + { + OwnPtr<WebCore::GraphicsContext> graphicsContext = bitmap->createGraphicsContext(); + graphicsContext->drawImage(image, ColorSpaceDeviceRGB, IntPoint::zero()); + } + + ShareableBitmap::Handle handle; + bitmap->createHandle(handle); + m_webPage->send(Messages::LayerTreeHostProxy::CreateDirectlyCompositedImage(key, handle)); + m_directlyCompositedImageRefCounts.add(key, 1); + return key; +} + +void LayerTreeHostQt::releaseImageBackingStore(int64_t key) +{ + if (!key) + return; + HashMap<int64_t, int>::iterator it = m_directlyCompositedImageRefCounts.find(key); + if (it == m_directlyCompositedImageRefCounts.end()) + return; + + it->second--; + + if (it->second) + return; + + m_directlyCompositedImageRefCounts.remove(it); + m_webPage->send(Messages::LayerTreeHostProxy::DestroyDirectlyCompositedImage(key)); +} + + +void LayerTreeHostQt::notifyAnimationStarted(const WebCore::GraphicsLayer*, double time) +{ +} + +void LayerTreeHostQt::notifySyncRequired(const WebCore::GraphicsLayer*) +{ +} + +void LayerTreeHostQt::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect) +{ + if (graphicsLayer == m_nonCompositedContentLayer) { + m_webPage->drawRect(graphicsContext, clipRect); + return; + } + + if (graphicsLayer == m_pageOverlayLayer) { + // Overlays contain transparent contents and won't clear the context as part of their rendering, so we do it here. + graphicsContext.clearRect(clipRect); + m_webPage->drawPageOverlay(graphicsContext, clipRect); + return; + } +} + +bool LayerTreeHostQt::showDebugBorders() const +{ + return m_webPage->corePage()->settings()->showDebugBorders(); +} + +bool LayerTreeHostQt::showRepaintCounter() const +{ + return m_webPage->corePage()->settings()->showRepaintCounter(); +} + +bool LayerTreeHost::supportsAcceleratedCompositing() +{ + return true; +} + +#if USE(TILED_BACKING_STORE) +void LayerTreeHostQt::createTile(WebLayerID layerID, int tileID, const UpdateInfo& updateInfo) +{ + m_webPage->send(Messages::LayerTreeHostProxy::CreateTileForLayer(layerID, tileID, updateInfo)); +} + +void LayerTreeHostQt::updateTile(WebLayerID layerID, int tileID, const UpdateInfo& updateInfo) +{ + m_webPage->send(Messages::LayerTreeHostProxy::UpdateTileForLayer(layerID, tileID, updateInfo)); +} +void LayerTreeHostQt::removeTile(WebLayerID layerID, int tileID) +{ + m_webPage->send(Messages::LayerTreeHostProxy::RemoveTileForLayer(layerID, tileID)); +} + +void LayerTreeHostQt::setVisibleContentRectForLayer(int layerID, const WebCore::IntRect& rect) +{ + WebGraphicsLayer* layer = WebGraphicsLayer::layerByID(layerID); + if (!layer) + return; + FloatRect visibleRect(rect); + layer->setVisibleContentRect(rect); +} + +void LayerTreeHostQt::setVisibleContentRectAndScale(const IntRect& rect, float scale) +{ + WebGraphicsLayer* layer = toWebGraphicsLayer(m_rootLayer.get()); + if (!layer) + return; + layer->setContentsScale(scale); + toWebGraphicsLayer(m_nonCompositedContentLayer.get())->setVisibleContentRect(rect); +} + +void LayerTreeHostQt::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector) +{ + toWebGraphicsLayer(m_nonCompositedContentLayer.get())->setVisibleContentRectTrajectoryVector(trajectoryVector); +} + +void LayerTreeHostQt::renderNextFrame() +{ + m_waitingForUIProcess = false; + scheduleLayerFlush(); +} + +bool LayerTreeHostQt::layerTreeTileUpdatesAllowed() const +{ + return !m_isSuspended && !m_waitingForUIProcess; +} + +void LayerTreeHostQt::purgeBackingStores() +{ + m_shouldRecreateBackingStore = true; + WebGraphicsLayer* webRootLayer = toWebGraphicsLayer(m_rootLayer.get()); + webRootLayer->purgeBackingStores(); + + ASSERT(!m_directlyCompositedImageRefCounts.size()); +} + +void LayerTreeHostQt::recreateBackingStoreIfNeeded() +{ + if (!m_shouldRecreateBackingStore) + return; + + m_shouldRecreateBackingStore = false; + WebGraphicsLayer* webRootLayer = toWebGraphicsLayer(m_rootLayer.get()); + webRootLayer->recreateBackingStoreIfNeeded(); +} +#endif + +} // namespace WebKit +#else +#include "LayerTreeHost.h" + +using namespace WebCore; + +namespace WebKit { + +bool LayerTreeHost::supportsAcceleratedCompositing() +{ + return false; +} + +} // namespace WebKit +#endif diff --git a/Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.h b/Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.h new file mode 100644 index 000000000..8527c528b --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/qt/LayerTreeHostQt.h @@ -0,0 +1,129 @@ +/* + Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef LayerTreeHostQt_h +#define LayerTreeHostQt_h + +#include "LayerTreeContext.h" +#include "LayerTreeHost.h" +#include "Timer.h" +#include "WebGraphicsLayer.h" +#include <WebCore/GraphicsLayerClient.h> +#include <wtf/OwnPtr.h> + +namespace WebKit { + +class UpdateInfo; +class WebPage; + +class LayerTreeHostQt : public LayerTreeHost, WebCore::GraphicsLayerClient +#if USE(TILED_BACKING_STORE) + , public WebLayerTreeTileClient +#endif +{ +public: + static PassRefPtr<LayerTreeHostQt> create(WebPage*); + virtual ~LayerTreeHostQt(); + + static bool supportsAcceleratedCompositing(); + + virtual const LayerTreeContext& layerTreeContext() { return m_layerTreeContext; } + virtual void setLayerFlushSchedulingEnabled(bool); + virtual void scheduleLayerFlush(); + virtual void setShouldNotifyAfterNextScheduledLayerFlush(bool); + virtual void setRootCompositingLayer(WebCore::GraphicsLayer*); + virtual void invalidate(); + + virtual void setNonCompositedContentsNeedDisplay(const WebCore::IntRect&); + virtual void scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& scrollOffset); + virtual void forceRepaint(); + virtual void sizeDidChange(const WebCore::IntSize& newSize); + + virtual void didInstallPageOverlay(); + virtual void didUninstallPageOverlay(); + virtual void setPageOverlayNeedsDisplay(const WebCore::IntRect&); + + virtual void pauseRendering() { m_isSuspended = true; } + virtual void resumeRendering() { m_isSuspended = false; scheduleLayerFlush(); } + virtual void deviceScaleFactorDidChange() { } + virtual int64_t adoptImageBackingStore(Image*); + virtual void releaseImageBackingStore(int64_t); + +#if USE(TILED_BACKING_STORE) + virtual void createTile(WebLayerID, int tileID, const UpdateInfo&); + virtual void updateTile(WebLayerID, int tileID, const UpdateInfo&); + virtual void removeTile(WebLayerID, int tileID); + virtual void setVisibleContentRectForLayer(int layerID, const WebCore::IntRect&); + virtual void renderNextFrame(); + virtual void purgeBackingStores(); + virtual bool layerTreeTileUpdatesAllowed() const; + virtual void setVisibleContentRectAndScale(const IntRect&, float scale); + virtual void setVisibleContentRectTrajectoryVector(const FloatPoint&); + virtual void didSyncCompositingStateForLayer(const WebLayerInfo&); + virtual void didDeleteLayer(WebLayerID); +#endif + +protected: + explicit LayerTreeHostQt(WebPage*); + +private: + // GraphicsLayerClient + virtual void notifyAnimationStarted(const WebCore::GraphicsLayer*, double time); + virtual void notifySyncRequired(const WebCore::GraphicsLayer*); + virtual void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect); + virtual bool showDebugBorders() const; + virtual bool showRepaintCounter() const; + + // LayerTreeHostQt + void createPageOverlayLayer(); + void destroyPageOverlayLayer(); + bool flushPendingLayerChanges(); + void cancelPendingLayerFlush(); + void performScheduledLayerFlush(); + void sendLayersToUI(); + void recreateBackingStoreIfNeeded(); + + OwnPtr<WebCore::GraphicsLayer> m_rootLayer; + + // The layer which contains all non-composited content. + OwnPtr<WebCore::GraphicsLayer> m_nonCompositedContentLayer; + + // The page overlay layer. Will be null if there's no page overlay. + OwnPtr<WebCore::GraphicsLayer> m_pageOverlayLayer; + + HashMap<int64_t, int> m_directlyCompositedImageRefCounts; + + bool m_notifyAfterScheduledLayerFlush; + bool m_isValid; +#if USE(TILED_BACKING_STORE) + bool m_waitingForUIProcess; + bool m_isSuspended; +#endif + LayerTreeContext m_layerTreeContext; + bool m_shouldSyncFrame; + bool m_shouldSyncRootLayer; + void layerFlushTimerFired(WebCore::Timer<LayerTreeHostQt>*); + WebCore::Timer<LayerTreeHostQt> m_layerFlushTimer; + bool m_layerFlushSchedulingEnabled; + bool m_shouldRecreateBackingStore; +}; + +} + +#endif // LayerTreeHostQt_h diff --git a/Source/WebKit2/WebProcess/WebPage/qt/WebInspectorQt.cpp b/Source/WebKit2/WebProcess/WebPage/qt/WebInspectorQt.cpp new file mode 100644 index 000000000..1a3b598a3 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/qt/WebInspectorQt.cpp @@ -0,0 +1,44 @@ +/* + * 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 "config.h" +#include "WebInspector.h" + +#if ENABLE(INSPECTOR) + +#include <WebCore/NotImplemented.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +String WebInspector::localizedStringsURL() const +{ + notImplemented(); + return String(); +} + +} // namespace WebKit + +#endif // ENABLE(INSPECTOR) diff --git a/Source/WebKit2/WebProcess/WebPage/qt/WebPageQt.cpp b/Source/WebKit2/WebProcess/WebPage/qt/WebPageQt.cpp new file mode 100644 index 000000000..55080d03c --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/qt/WebPageQt.cpp @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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 "config.h" +#include "WebPage.h" + +#include "NotImplemented.h" +#include "WebEditorClient.h" +#include "WebEvent.h" +#include "WebPageProxyMessages.h" +#include "WebProcess.h" +#include <WebCore/FocusController.h> +#include <WebCore/Frame.h> +#include <WebCore/KeyboardEvent.h> +#include <WebCore/Page.h> +#include <WebCore/PlatformKeyboardEvent.h> +#include <WebCore/Range.h> +#include <WebCore/Settings.h> +#include <WebCore/Text.h> +#include <WebCore/TextIterator.h> + +#ifndef VK_UNKNOWN +#define VK_UNKNOWN 0 +#define VK_BACK 0x08 +#define VK_TAB 0x09 +#define VK_CLEAR 0x0C +#define VK_RETURN 0x0D +#define VK_SHIFT 0x10 +#define VK_CONTROL 0x11 // CTRL key +#define VK_MENU 0x12 // ALT key +#define VK_PAUSE 0x13 // PAUSE key +#define VK_CAPITAL 0x14 // CAPS LOCK key +#define VK_KANA 0x15 // Input Method Editor (IME) Kana mode +#define VK_HANGUL 0x15 // IME Hangul mode +#define VK_JUNJA 0x17 // IME Junja mode +#define VK_FINAL 0x18 // IME final mode +#define VK_HANJA 0x19 // IME Hanja mode +#define VK_KANJI 0x19 // IME Kanji mode +#define VK_ESCAPE 0x1B // ESC key +#define VK_CONVERT 0x1C // IME convert +#define VK_NONCONVERT 0x1D // IME nonconvert +#define VK_ACCEPT 0x1E // IME accept +#define VK_MODECHANGE 0x1F // IME mode change request +#define VK_SPACE 0x20 // SPACE key +#define VK_PRIOR 0x21 // PAGE UP key +#define VK_NEXT 0x22 // PAGE DOWN key +#define VK_END 0x23 // END key +#define VK_HOME 0x24 // HOME key +#define VK_LEFT 0x25 // LEFT ARROW key +#define VK_UP 0x26 // UP ARROW key +#define VK_RIGHT 0x27 // RIGHT ARROW key +#define VK_DOWN 0x28 // DOWN ARROW key +#define VK_SELECT 0x29 // SELECT key +#define VK_PRINT 0x2A // PRINT key +#define VK_EXECUTE 0x2B // EXECUTE key +#define VK_SNAPSHOT 0x2C // PRINT SCREEN key +#define VK_INSERT 0x2D // INS key +#define VK_DELETE 0x2E // DEL key +#define VK_HELP 0x2F // HELP key +// Windows 2000/XP: For any country/region, the '.' key +#define VK_OEM_PERIOD 0xBE +#endif + +using namespace WebCore; + +namespace WebKit { + +void WebPage::platformInitialize() +{ + Settings* settings = m_page->settings(); + + // If accelerated compositing is enabled, we want to be in force-compositing mode, so that we don't switch between composited/non-composited state. + settings->setForceCompositingMode(true); +} + +void WebPage::platformPreferencesDidChange(const WebPreferencesStore&) +{ +} + +static const unsigned CtrlKey = 1 << 0; +static const unsigned AltKey = 1 << 1; +static const unsigned ShiftKey = 1 << 2; + +struct KeyDownEntry { + unsigned virtualKey; + unsigned modifiers; + const char* name; +}; + +struct KeyPressEntry { + unsigned charCode; + unsigned modifiers; + const char* name; +}; + +static const KeyDownEntry keyDownEntries[] = { + { VK_LEFT, 0, "MoveLeft" }, + { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, + { VK_LEFT, CtrlKey, "MoveWordLeft" }, + { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" }, + { VK_RIGHT, 0, "MoveRight" }, + { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, + { VK_RIGHT, CtrlKey, "MoveWordRight" }, + { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" }, + { VK_UP, 0, "MoveUp" }, + { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, + { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" }, + { VK_DOWN, 0, "MoveDown" }, + { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, + { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" }, + { VK_PRIOR, 0, "MovePageUp" }, + { VK_NEXT, 0, "MovePageDown" }, + { VK_HOME, 0, "MoveToBeginningOfLine" }, + { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" }, + { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" }, + { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" }, + + { VK_END, 0, "MoveToEndOfLine" }, + { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" }, + { VK_END, CtrlKey, "MoveToEndOfDocument" }, + { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" }, + + { VK_BACK, 0, "DeleteBackward" }, + { VK_BACK, ShiftKey, "DeleteBackward" }, + { VK_DELETE, 0, "DeleteForward" }, + { VK_BACK, CtrlKey, "DeleteWordBackward" }, + { VK_DELETE, CtrlKey, "DeleteWordForward" }, + + { 'B', CtrlKey, "ToggleBold" }, + { 'I', CtrlKey, "ToggleItalic" }, + + { VK_ESCAPE, 0, "Cancel" }, + { VK_OEM_PERIOD, CtrlKey, "Cancel" }, + { VK_TAB, 0, "InsertTab" }, + { VK_TAB, ShiftKey, "InsertBacktab" }, + { VK_RETURN, 0, "InsertNewline" }, + { VK_RETURN, CtrlKey, "InsertNewline" }, + { VK_RETURN, AltKey, "InsertNewline" }, + { VK_RETURN, ShiftKey, "InsertNewline" }, + { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, + + // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled + // in the application or in WebKit. We chose WebKit. + { 'C', CtrlKey, "Copy" }, + { 'V', CtrlKey, "Paste" }, + { 'X', CtrlKey, "Cut" }, + { 'A', CtrlKey, "SelectAll" }, + { VK_INSERT, CtrlKey, "Copy" }, + { VK_DELETE, ShiftKey, "Cut" }, + { VK_INSERT, ShiftKey, "Paste" }, + { 'Z', CtrlKey, "Undo" }, + { 'Z', CtrlKey | ShiftKey, "Redo" }, +}; + +static const KeyPressEntry keyPressEntries[] = { + { '\t', 0, "InsertTab" }, + { '\t', ShiftKey, "InsertBacktab" }, + { '\r', 0, "InsertNewline" }, + { '\r', CtrlKey, "InsertNewline" }, + { '\r', AltKey, "InsertNewline" }, + { '\r', ShiftKey, "InsertNewline" }, + { '\r', AltKey | ShiftKey, "InsertNewline" }, +}; + +const char* WebPage::interpretKeyEvent(const KeyboardEvent* evt) +{ + ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent); + + static HashMap<int, const char*>* keyDownCommandsMap = 0; + static HashMap<int, const char*>* keyPressCommandsMap = 0; + + if (!keyDownCommandsMap) { + keyDownCommandsMap = new HashMap<int, const char*>; + keyPressCommandsMap = new HashMap<int, const char*>; + + for (unsigned i = 0; i < (sizeof(keyDownEntries) / sizeof(keyDownEntries[0])); i++) + keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); + + for (unsigned i = 0; i < (sizeof(keyPressEntries) / sizeof(keyPressEntries[0])); i++) + keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); + } + + unsigned modifiers = 0; + if (evt->shiftKey()) + modifiers |= ShiftKey; + if (evt->altKey()) + modifiers |= AltKey; + if (evt->ctrlKey()) + modifiers |= CtrlKey; + + if (evt->type() == eventNames().keydownEvent) { + int mapKey = modifiers << 16 | evt->keyEvent()->windowsVirtualKeyCode(); + return mapKey ? keyDownCommandsMap->get(mapKey) : 0; + } + + int mapKey = modifiers << 16 | evt->charCode(); + return mapKey ? keyPressCommandsMap->get(mapKey) : 0; +} + +static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity) +{ + page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity); +} + +static inline void logicalScroll(Page* page, ScrollLogicalDirection direction, ScrollGranularity granularity) +{ + page->focusController()->focusedOrMainFrame()->eventHandler()->logicalScrollRecursively(direction, granularity); +} + +bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) +{ + if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown) + return false; + + switch (keyboardEvent.windowsVirtualKeyCode()) { + case VK_BACK: + if (keyboardEvent.shiftKey()) + m_page->goForward(); + else + m_page->goBack(); + break; + case VK_SPACE: + logicalScroll(m_page.get(), keyboardEvent.shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward, ScrollByPage); + break; + case VK_LEFT: + scroll(m_page.get(), ScrollLeft, ScrollByLine); + break; + case VK_RIGHT: + scroll(m_page.get(), ScrollRight, ScrollByLine); + break; + case VK_UP: + scroll(m_page.get(), ScrollUp, ScrollByLine); + break; + case VK_DOWN: + scroll(m_page.get(), ScrollDown, ScrollByLine); + break; + case VK_HOME: + logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument); + break; + case VK_END: + logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument); + break; + case VK_PRIOR: + logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage); + break; + case VK_NEXT: + logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage); + break; + default: + return false; + } + + return true; +} + +bool WebPage::platformHasLocalDataForURL(const KURL&) +{ + notImplemented(); + return false; +} + +String WebPage::cachedResponseMIMETypeForURL(const KURL&) +{ + notImplemented(); + return String(); +} + +bool WebPage::platformCanHandleRequest(const ResourceRequest&) +{ + notImplemented(); + return true; +} + +String WebPage::cachedSuggestedFilenameForURL(const KURL&) +{ + notImplemented(); + return String(); +} + +PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&) +{ + notImplemented(); + return 0; +} + +static Frame* targetFrameForEditing(WebPage* page) +{ + Frame* targetFrame = page->corePage()->focusController()->focusedOrMainFrame(); + + if (!targetFrame || !targetFrame->editor()) + return 0; + + Editor* editor = targetFrame->editor(); + if (!editor->canEdit()) + return 0; + + if (editor->hasComposition()) { + // We should verify the parent node of this IME composition node are + // editable because JavaScript may delete a parent node of the composition + // node. In this case, WebKit crashes while deleting texts from the parent + // node, which doesn't exist any longer. + if (PassRefPtr<Range> range = editor->compositionRange()) { + Node* node = range->startContainer(); + if (!node || !node->isContentEditable()) + return 0; + } + } + return targetFrame; +} + +void WebPage::confirmComposition(const String& compositionString, int64_t selectionStart, int64_t selectionLength) +{ + Frame* targetFrame = targetFrameForEditing(this); + if (!targetFrame) + return; + + Editor* editor = targetFrame->editor(); + editor->confirmComposition(compositionString); + + RefPtr<Range> selectionRange; + if (selectionStart != -1) { + Element* scope = targetFrame->selection()->rootEditableElement(); + selectionRange = TextIterator::rangeFromLocationAndLength(scope, selectionStart, selectionLength); + ASSERT_WITH_MESSAGE(selectionRange, "Invalid selection: [%lld:%lld] in text of length %d", static_cast<long long>(selectionStart), static_cast<long long>(selectionLength), scope->innerText().length()); + } + + if (selectionRange) { + VisibleSelection selection(selectionRange.get(), SEL_DEFAULT_AFFINITY); + targetFrame->selection()->setSelection(selection); + } + + // FIXME: static_cast<WebEditorClient*>(editor->client())->sendSelectionChangedMessage(); +} + +void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementStart, uint64_t replacementLength) +{ + Frame* targetFrame = targetFrameForEditing(this); + if (!targetFrame) + return; + + Element* scope = targetFrame->selection()->rootEditableElement(); + + if (targetFrame->selection()->isContentEditable()) { + if (replacementLength > 0) { + // The layout needs to be uptodate before setting a selection + targetFrame->document()->updateLayout(); + + RefPtr<Range> replacementRange = TextIterator::rangeFromLocationAndLength(scope, replacementStart, replacementLength); + + targetFrame->editor()->setIgnoreCompositionSelectionChange(true); + targetFrame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY)); + targetFrame->editor()->setIgnoreCompositionSelectionChange(false); + } + + targetFrame->editor()->setComposition(text, underlines, selectionStart, selectionEnd); + + // FIXME: static_cast<WebEditorClient*>(targetFrame->editor()->client())->sendSelectionChangedMessage(); + } +} + +void WebPage::cancelComposition() +{ + Frame* frame = targetFrameForEditing(this); + + frame->editor()->cancelComposition(); + + // FIXME: static_cast<WebEditorClient*>(targetFrame->editor()->client())->sendSelectionChangedMessage(); +} + +void WebPage::registerApplicationScheme(const String& scheme) +{ + QtNetworkAccessManager* qnam = qobject_cast<QtNetworkAccessManager*>(WebProcess::shared().networkAccessManager()); + if (!qnam) + return; + qnam->registerApplicationScheme(this, QString(scheme)); +} + +void WebPage::receivedApplicationSchemeRequest(const QNetworkRequest& request, QtNetworkReply* reply) +{ + QtNetworkRequestData requestData(request, reply); + m_applicationSchemeReplies.add(requestData.m_replyUuid, reply); + send(Messages::WebPageProxy::ResolveApplicationSchemeRequest(requestData)); +} + +void WebPage::applicationSchemeReply(const QtNetworkReplyData& replyData) +{ + if (!m_applicationSchemeReplies.contains(replyData.m_replyUuid)) + return; + + QtNetworkReply* networkReply = m_applicationSchemeReplies.take(replyData.m_replyUuid); + networkReply->setReplyData(replyData); + networkReply->finalize(); +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/win/DrawingAreaImplWin.cpp b/Source/WebKit2/WebProcess/WebPage/win/DrawingAreaImplWin.cpp new file mode 100644 index 000000000..4feb001fa --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/win/DrawingAreaImplWin.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "DrawingAreaImpl.h" + +#include "ShareableBitmap.h" +#include "UpdateInfo.h" +#include "WebPage.h" +#include "WebPageProxyMessages.h" +#include "WindowGeometry.h" +#include <WebCore/GraphicsContext.h> + +using namespace WebCore; + +namespace WebKit { + +void DrawingAreaImpl::scheduleChildWindowGeometryUpdate(const WindowGeometry& geometry) +{ +#if USE(ACCELERATED_COMPOSITING) + if (m_layerTreeHost) { + m_layerTreeHost->scheduleChildWindowGeometryUpdate(geometry); + return; + } +#endif + + // FIXME: This should be a Messages::DrawingAreaProxy, and DrawingAreaProxy should pass the + // data off to the WebPageProxy. + m_webPage->send(Messages::WebPageProxy::ScheduleChildWindowGeometryUpdate(geometry)); +} + +PassOwnPtr<GraphicsContext> DrawingAreaImpl::createGraphicsContext(ShareableBitmap* bitmap) +{ + HDC bitmapDC = bitmap->windowsContext(); + // FIXME: We should really be checking m_webPage->draws[Transparent]Background() to determine + // whether to have an alpha channel or not. But currently we always render into a non-layered + // window, so the alpha channel doesn't matter anyway. + return adoptPtr(new GraphicsContext(bitmapDC, false)); +} + +} // namespace WebKit + diff --git a/Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp b/Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp new file mode 100644 index 000000000..57c04bbf0 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/win/LayerTreeHostWin.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 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 "config.h" +#include "LayerTreeHost.h" + +#if USE(CA) +#include "LayerTreeHostCAWin.h" +#endif + +namespace WebKit { + +bool LayerTreeHost::supportsAcceleratedCompositing() +{ +#if USE(CA) && HAVE(WKQCA) + return LayerTreeHostCAWin::supportsAcceleratedCompositing(); +#else + return false; +#endif +} + +} // namespace WebKit diff --git a/Source/WebKit2/WebProcess/WebPage/win/WebInspectorWin.cpp b/Source/WebKit2/WebProcess/WebPage/win/WebInspectorWin.cpp new file mode 100644 index 000000000..5ada45d41 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/win/WebInspectorWin.cpp @@ -0,0 +1,48 @@ +/* + * 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 "config.h" +#include "WebInspector.h" + +#if ENABLE(INSPECTOR) + +#include "WebKitBundle.h" +#include <wtf/RetainPtr.h> +#include <wtf/text/WTFString.h> + +namespace WebKit { + +String WebInspector::localizedStringsURL() const +{ + RetainPtr<CFURLRef> localizedStringsURLRef(AdoptCF, CFBundleCopyResourceURL(webKitBundle(), CFSTR("localizedStrings"), CFSTR("js"), 0)); + if (!localizedStringsURLRef) + return String(); + + return String(CFURLGetString(localizedStringsURLRef.get())); +} + +} // namespace WebKit + +#endif // ENABLE(INSPECTOR) diff --git a/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp b/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp new file mode 100644 index 000000000..19f760f6a --- /dev/null +++ b/Source/WebKit2/WebProcess/WebPage/win/WebPageWin.cpp @@ -0,0 +1,468 @@ +/* + * 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 "config.h" +#include "WebPage.h" + +#include "FontSmoothingLevel.h" +#include "WebCoreArgumentCoders.h" +#include "WebEvent.h" +#include "WebPageProxyMessages.h" +#include "WebPreferencesStore.h" +#include "WebProcess.h" +#include <WebCore/FocusController.h> +#include <WebCore/FontRenderingMode.h> +#include <WebCore/Frame.h> +#include <WebCore/FrameView.h> +#include <WebCore/HitTestRequest.h> +#include <WebCore/HitTestResult.h> +#include <WebCore/KeyboardEvent.h> +#include <WebCore/Page.h> +#include <WebCore/PlatformKeyboardEvent.h> +#include <WebCore/RenderLayer.h> +#include <WebCore/RenderView.h> +#include <WebCore/ResourceHandle.h> +#include <WebCore/Settings.h> +#if USE(CG) +#include <WebKitSystemInterface/WebKitSystemInterface.h> +#endif +#include <WinUser.h> + +#if USE(CFNETWORK) +#include <CFNetwork/CFURLCachePriv.h> +#include <CFNetwork/CFURLProtocolPriv.h> +#include <CFNetwork/CFURLRequestPriv.h> +#endif + +using namespace WebCore; + +namespace WebKit { + +void WebPage::platformInitialize() +{ +} + +void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store) +{ + FontSmoothingLevel fontSmoothingLevel = static_cast<FontSmoothingLevel>(store.getUInt32ValueForKey(WebPreferencesKey::fontSmoothingLevelKey())); + +#if USE(CG) + FontSmoothingLevel adjustedLevel = fontSmoothingLevel; + if (adjustedLevel == FontSmoothingLevelWindows) + adjustedLevel = FontSmoothingLevelMedium; + wkSetFontSmoothingLevel(adjustedLevel); +#endif + + m_page->settings()->setFontRenderingMode(fontSmoothingLevel == FontSmoothingLevelWindows ? AlternateRenderingMode : NormalRenderingMode); +} + +static const unsigned CtrlKey = 1 << 0; +static const unsigned AltKey = 1 << 1; +static const unsigned ShiftKey = 1 << 2; + +struct KeyDownEntry { + unsigned virtualKey; + unsigned modifiers; + const char* name; +}; + +struct KeyPressEntry { + unsigned charCode; + unsigned modifiers; + const char* name; +}; + +static const KeyDownEntry keyDownEntries[] = { + { VK_LEFT, 0, "MoveLeft" }, + { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, + { VK_LEFT, CtrlKey, "MoveWordLeft" }, + { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" }, + { VK_RIGHT, 0, "MoveRight" }, + { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, + { VK_RIGHT, CtrlKey, "MoveWordRight" }, + { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" }, + { VK_UP, 0, "MoveUp" }, + { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, + { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" }, + { VK_DOWN, 0, "MoveDown" }, + { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, + { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" }, + { VK_PRIOR, 0, "MovePageUp" }, + { VK_NEXT, 0, "MovePageDown" }, + { VK_HOME, 0, "MoveToBeginningOfLine" }, + { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" }, + { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" }, + { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" }, + + { VK_END, 0, "MoveToEndOfLine" }, + { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" }, + { VK_END, CtrlKey, "MoveToEndOfDocument" }, + { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" }, + + { VK_BACK, 0, "DeleteBackward" }, + { VK_BACK, ShiftKey, "DeleteBackward" }, + { VK_DELETE, 0, "DeleteForward" }, + { VK_BACK, CtrlKey, "DeleteWordBackward" }, + { VK_DELETE, CtrlKey, "DeleteWordForward" }, + + { 'B', CtrlKey, "ToggleBold" }, + { 'I', CtrlKey, "ToggleItalic" }, + + { VK_ESCAPE, 0, "Cancel" }, + { VK_OEM_PERIOD, CtrlKey, "Cancel" }, + { VK_TAB, 0, "InsertTab" }, + { VK_TAB, ShiftKey, "InsertBacktab" }, + { VK_RETURN, 0, "InsertNewline" }, + { VK_RETURN, CtrlKey, "InsertNewline" }, + { VK_RETURN, AltKey, "InsertNewline" }, + { VK_RETURN, ShiftKey, "InsertNewline" }, + { VK_RETURN, AltKey | ShiftKey, "InsertNewline" }, + + // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled + // in the application or in WebKit. We chose WebKit. + { 'C', CtrlKey, "Copy" }, + { 'V', CtrlKey, "Paste" }, + { 'X', CtrlKey, "Cut" }, + { 'A', CtrlKey, "SelectAll" }, + { VK_INSERT, CtrlKey, "Copy" }, + { VK_DELETE, ShiftKey, "Cut" }, + { VK_INSERT, ShiftKey, "Paste" }, + { 'Z', CtrlKey, "Undo" }, + { 'Z', CtrlKey | ShiftKey, "Redo" }, +}; + +static const KeyPressEntry keyPressEntries[] = { + { '\t', 0, "InsertTab" }, + { '\t', ShiftKey, "InsertBacktab" }, + { '\r', 0, "InsertNewline" }, + { '\r', CtrlKey, "InsertNewline" }, + { '\r', AltKey, "InsertNewline" }, + { '\r', ShiftKey, "InsertNewline" }, + { '\r', AltKey | ShiftKey, "InsertNewline" }, +}; + +const char* WebPage::interpretKeyEvent(const KeyboardEvent* evt) +{ + ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent); + + static HashMap<int, const char*>* keyDownCommandsMap = 0; + static HashMap<int, const char*>* keyPressCommandsMap = 0; + + if (!keyDownCommandsMap) { + keyDownCommandsMap = new HashMap<int, const char*>; + keyPressCommandsMap = new HashMap<int, const char*>; + + for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i) + keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); + + for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i) + keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); + } + + unsigned modifiers = 0; + if (evt->shiftKey()) + modifiers |= ShiftKey; + if (evt->altKey()) + modifiers |= AltKey; + if (evt->ctrlKey()) + modifiers |= CtrlKey; + + if (evt->type() == eventNames().keydownEvent) { + int mapKey = modifiers << 16 | evt->keyCode(); + return mapKey ? keyDownCommandsMap->get(mapKey) : 0; + } + + int mapKey = modifiers << 16 | evt->charCode(); + return mapKey ? keyPressCommandsMap->get(mapKey) : 0; +} + +bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent) +{ + if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown) + return false; + + switch (keyboardEvent.windowsVirtualKeyCode()) { + case VK_BACK: + if (keyboardEvent.isSystemKey()) + return false; + if (keyboardEvent.shiftKey()) + m_page->goForward(); + else + m_page->goBack(); + break; + case VK_LEFT: + if (keyboardEvent.isSystemKey()) + m_page->goBack(); + else + scroll(m_page.get(), ScrollLeft, ScrollByLine); + break; + case VK_RIGHT: + if (keyboardEvent.isSystemKey()) + m_page->goForward(); + else + scroll(m_page.get(), ScrollRight, ScrollByLine); + break; + case VK_UP: + if (keyboardEvent.isSystemKey()) + return false; + scroll(m_page.get(), ScrollUp, ScrollByLine); + break; + case VK_DOWN: + if (keyboardEvent.isSystemKey()) + return false; + scroll(m_page.get(), ScrollDown, ScrollByLine); + break; + case VK_HOME: + if (keyboardEvent.isSystemKey()) + return false; + logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument); + break; + case VK_END: + if (keyboardEvent.isSystemKey()) + return false; + logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument); + break; + case VK_PRIOR: + if (keyboardEvent.isSystemKey()) + return false; + logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage); + break; + case VK_NEXT: + if (keyboardEvent.isSystemKey()) + return false; + logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage); + break; + default: + return false; + } + + return true; +} + +#if USE(CFNETWORK) +static RetainPtr<CFCachedURLResponseRef> cachedResponseForURL(WebPage* webPage, const KURL& url) +{ + RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL()); + RetainPtr<CFMutableURLRequestRef> request(AdoptCF, CFURLRequestCreateMutable(0, cfURL.get(), kCFURLRequestCachePolicyReloadIgnoringCache, 60, 0)); +#if USE(CFURLSTORAGESESSIONS) + wkSetRequestStorageSession(ResourceHandle::currentStorageSession(), request.get()); +#endif + + RetainPtr<CFStringRef> userAgent(AdoptCF, webPage->userAgent().createCFString()); + CFURLRequestSetHTTPHeaderFieldValue(request.get(), CFSTR("User-Agent"), userAgent.get()); + + RetainPtr<CFURLCacheRef> cache; +#if USE(CFURLSTORAGESESSIONS) + if (CFURLStorageSessionRef currentStorageSession = ResourceHandle::currentStorageSession()) + cache.adoptCF(wkCopyURLCache(currentStorageSession)); + else +#endif + cache.adoptCF(CFURLCacheCopySharedURLCache()); + + RetainPtr<CFCachedURLResponseRef> response(AdoptCF, CFURLCacheCopyResponseForRequest(cache.get(), request.get())); + return response; +} +#endif + +bool WebPage::platformHasLocalDataForURL(const KURL& url) +{ +#if USE(CFNETWORK) + return cachedResponseForURL(this, url); +#else + return false; +#endif +} + +String WebPage::cachedResponseMIMETypeForURL(const KURL& url) +{ +#if USE(CFNETWORK) + RetainPtr<CFCachedURLResponseRef> cachedResponse = cachedResponseForURL(this, url); + CFURLResponseRef response = CFCachedURLResponseGetWrappedResponse(cachedResponse.get()); + return response ? CFURLResponseGetMIMEType(response) : String(); +#else + return String(); +#endif +} + +String WebPage::cachedSuggestedFilenameForURL(const KURL& url) +{ +#if USE(CFNETWORK) + RetainPtr<CFCachedURLResponseRef> cachedResponse = cachedResponseForURL(this, url); + CFURLResponseRef response = CFCachedURLResponseGetWrappedResponse(cachedResponse.get()); + if (!response) + return String(); + RetainPtr<CFStringRef> suggestedFilename(AdoptCF, CFURLResponseCopySuggestedFilename(response)); + + return suggestedFilename.get(); +#else + return String(); +#endif +} + +PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL& url) +{ +#if USE(CFNETWORK) + RetainPtr<CFCachedURLResponseRef> cachedResponse = cachedResponseForURL(this, url); + CFDataRef data = CFCachedURLResponseGetReceiverData(cachedResponse.get()); + if (!data) + return 0; + + return SharedBuffer::wrapCFData(data); +#else + return 0; +#endif +} + +bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request) +{ +#if USE(CFNETWORK) + return CFURLProtocolCanHandleRequest(request.cfURLRequest()); +#else + return true; +#endif +} + +void WebPage::confirmComposition(const String& compositionString) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || !frame->editor()->canEdit()) + return; + frame->editor()->confirmComposition(compositionString); +} + +void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame || !frame->editor()->canEdit()) + return; + frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0); +} + +void WebPage::firstRectForCharacterInSelectedRange(const uint64_t characterPosition, WebCore::IntRect& resultRect) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + IntRect rect; + if (RefPtr<Range> range = frame->editor()->hasComposition() ? frame->editor()->compositionRange() : frame->selection()->selection().toNormalizedRange()) { + ExceptionCode ec = 0; + RefPtr<Range> tempRange = range->cloneRange(ec); + tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + characterPosition, ec); + rect = frame->editor()->firstRectForRange(tempRange.get()); + } + resultRect = frame->view()->contentsToWindow(rect); +} + +void WebPage::getSelectedText(String& text) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange(); + text = selectedRange->text(); +} + +void WebPage::gestureWillBegin(const WebCore::IntPoint& point, bool& canBeginPanning) +{ + m_gestureReachedScrollingLimit = false; + + bool hitScrollbar = false; + + HitTestRequest request(HitTestRequest::ReadOnly); + for (Frame* childFrame = m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) { + ScrollView* scollView = childFrame->view(); + if (!scollView) + break; + + RenderView* renderView = childFrame->document()->renderView(); + if (!renderView) + break; + + RenderLayer* layer = renderView->layer(); + if (!layer) + break; + + HitTestResult result = scollView->windowToContents(point); + layer->hitTest(request, result); + m_gestureTargetNode = result.innerNode(); + + if (!hitScrollbar) + hitScrollbar = result.scrollbar(); + } + + if (hitScrollbar) { + canBeginPanning = false; + return; + } + + if (!m_gestureTargetNode) { + canBeginPanning = false; + return; + } + + for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) { + if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) { + canBeginPanning = true; + return; + } + } + + canBeginPanning = false; +} + +static bool scrollbarAtTopOrBottomOfDocument(Scrollbar* scrollbar) +{ + ASSERT_ARG(scrollbar, scrollbar); + return !scrollbar->currentPos() || scrollbar->currentPos() >= scrollbar->maximum(); +} + +void WebPage::gestureDidScroll(const IntSize& size) +{ + ASSERT_ARG(size, !size.isZero()); + + if (!m_gestureTargetNode || !m_gestureTargetNode->renderer() || !m_gestureTargetNode->renderer()->enclosingLayer()) + return; + + Scrollbar* verticalScrollbar = 0; + if (Frame* frame = m_page->mainFrame()) { + if (ScrollView* view = frame->view()) + verticalScrollbar = view->verticalScrollbar(); + } + + m_gestureTargetNode->renderer()->enclosingLayer()->scrollByRecursively(size.width(), size.height()); + bool gestureReachedScrollingLimit = verticalScrollbar && scrollbarAtTopOrBottomOfDocument(verticalScrollbar); + + // FIXME: We really only want to update this state if the state was updated via scrolling the main frame, + // not scrolling something in a main frame when the main frame had already reached its scrolling limit. + + if (gestureReachedScrollingLimit == m_gestureReachedScrollingLimit) + return; + + send(Messages::WebPageProxy::SetGestureReachedScrollingLimit(gestureReachedScrollingLimit)); + m_gestureReachedScrollingLimit = gestureReachedScrollingLimit; +} + +void WebPage::gestureDidEnd() +{ + m_gestureTargetNode = nullptr; +} + +} // namespace WebKit |
