1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Portions Copyright (c) 2010 Motorola Mobility, Inc.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include "config.h"
28#include "ChunkedUpdateDrawingAreaProxy.h"
29
30#include "DrawingAreaMessageKinds.h"
31#include "DrawingAreaProxyMessageKinds.h"
32#include "MessageID.h"
33#include "UpdateChunk.h"
34#include "WebCoreArgumentCoders.h"
35#include "WebPageProxy.h"
36#include "WebProcessProxy.h"
37
38using namespace WebCore;
39
40namespace WebKit {
41
42PassOwnPtr<ChunkedUpdateDrawingAreaProxy> ChunkedUpdateDrawingAreaProxy::create(PlatformWebView* webView, WebPageProxy* webPageProxy)
43{
44    return adoptPtr(new ChunkedUpdateDrawingAreaProxy(webView, webPageProxy));
45}
46
47ChunkedUpdateDrawingAreaProxy::ChunkedUpdateDrawingAreaProxy(PlatformWebView* webView, WebPageProxy* webPageProxy)
48    : DrawingAreaProxy(DrawingAreaTypeChunkedUpdate, webPageProxy)
49    , m_isWaitingForDidSetFrameNotification(false)
50    , m_isVisible(true)
51    , m_forceRepaintWhenResumingPainting(false)
52#if PLATFORM(GTK)
53    , m_backingStoreImage(0)
54#endif
55    , m_webView(webView)
56{
57}
58
59ChunkedUpdateDrawingAreaProxy::~ChunkedUpdateDrawingAreaProxy()
60{
61}
62
63bool ChunkedUpdateDrawingAreaProxy::paint(const IntRect& rect, PlatformDrawingContext context)
64{
65    if (m_isWaitingForDidSetFrameNotification) {
66        WebPageProxy* page = this->page();
67        if (!page->isValid())
68            return false;
69
70        if (page->process()->isLaunching())
71            return false;
72
73        OwnPtr<CoreIPC::ArgumentDecoder> arguments = page->process()->connection()->deprecatedWaitFor(DrawingAreaProxyLegacyMessage::DidSetSize, page->pageID(), 0.04);
74        if (arguments)
75            didReceiveMessage(page->process()->connection(), CoreIPC::MessageID(DrawingAreaProxyLegacyMessage::DidSetSize), arguments.get());
76    }
77
78    return platformPaint(rect, context);
79}
80
81void ChunkedUpdateDrawingAreaProxy::sizeDidChange()
82{
83    sendSetSize();
84}
85
86void ChunkedUpdateDrawingAreaProxy::setPageIsVisible(bool isVisible)
87{
88    WebPageProxy* page = this->page();
89
90    if (isVisible == m_isVisible)
91        return;
92
93    m_isVisible = isVisible;
94    if (!page->isValid())
95        return;
96
97    if (!m_isVisible) {
98        // Tell the web process that it doesn't need to paint anything for now.
99        page->process()->deprecatedSend(DrawingAreaLegacyMessage::SuspendPainting, page->pageID(), CoreIPC::In());
100        return;
101    }
102
103    // The page is now visible, resume painting.
104    page->process()->deprecatedSend(DrawingAreaLegacyMessage::ResumePainting, page->pageID(), CoreIPC::In(m_forceRepaintWhenResumingPainting));
105    m_forceRepaintWhenResumingPainting = false;
106}
107
108void ChunkedUpdateDrawingAreaProxy::didSetSize(UpdateChunk* updateChunk)
109{
110    ASSERT(m_isWaitingForDidSetFrameNotification);
111    m_isWaitingForDidSetFrameNotification = false;
112
113    IntSize viewSize = updateChunk->rect().size();
114
115    if (viewSize != m_size)
116        sendSetSize();
117
118    invalidateBackingStore();
119    if (!updateChunk->isEmpty())
120        drawUpdateChunkIntoBackingStore(updateChunk);
121}
122
123void ChunkedUpdateDrawingAreaProxy::deprecatedUpdate(UpdateChunk* updateChunk)
124{
125    if (!m_isVisible) {
126        // We got an update request that must have been sent before we told the web process to suspend painting.
127        // Don't paint this into the backing store, because that could leave the backing store in an inconsistent state.
128        // Instead, we will just tell the drawing area to repaint everything when we resume painting.
129        m_forceRepaintWhenResumingPainting = true;
130    } else {
131        // Just paint into backing store.
132        drawUpdateChunkIntoBackingStore(updateChunk);
133    }
134
135    WebPageProxy* page = this->page();
136    page->process()->deprecatedSend(DrawingAreaLegacyMessage::DidUpdate, page->pageID(), CoreIPC::In());
137}
138
139void ChunkedUpdateDrawingAreaProxy::sendSetSize()
140{
141    if (!m_webPageProxy->isValid())
142        return;
143
144    if (m_isWaitingForDidSetFrameNotification)
145        return;
146    m_isWaitingForDidSetFrameNotification = true;
147
148    m_webPageProxy->process()->deprecatedSend(DrawingAreaLegacyMessage::SetSize, m_webPageProxy->pageID(), CoreIPC::In(m_size));
149}
150
151void ChunkedUpdateDrawingAreaProxy::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID messageID, CoreIPC::ArgumentDecoder* arguments)
152{
153    switch (messageID.get<DrawingAreaProxyLegacyMessage::Kind>()) {
154        case DrawingAreaProxyLegacyMessage::Update: {
155            UpdateChunk updateChunk;
156            if (!arguments->decode(updateChunk))
157                return;
158
159            deprecatedUpdate(&updateChunk);
160            break;
161        }
162        case DrawingAreaProxyLegacyMessage::DidSetSize: {
163            UpdateChunk updateChunk;
164            if (!arguments->decode(CoreIPC::Out(updateChunk)))
165                return;
166
167            didSetSize(&updateChunk);
168            break;
169        }
170        default:
171            ASSERT_NOT_REACHED();
172    }
173}
174
175} // namespace WebKit
176