Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebPagePopupImpl.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "WebPagePopupImpl.h"
33
34 #include "WebInputEventConversion.h"
35 #include "WebSettingsImpl.h"
36 #include "WebViewClient.h"
37 #include "WebViewImpl.h"
38 #include "WebWidgetClient.h"
39 #include "core/dom/ContextFeatures.h"
40 #include "core/frame/FrameView.h"
41 #include "core/frame/LocalFrame.h"
42 #include "core/loader/EmptyClients.h"
43 #include "core/loader/FrameLoadRequest.h"
44 #include "core/page/Chrome.h"
45 #include "core/page/DOMWindowPagePopup.h"
46 #include "core/page/EventHandler.h"
47 #include "core/page/FocusController.h"
48 #include "core/page/Page.h"
49 #include "core/page/PagePopupClient.h"
50 #include "core/frame/Settings.h"
51 #include "public/platform/WebCursorInfo.h"
52
53 using namespace WebCore;
54 using namespace std;
55
56 namespace blink {
57
58 class PagePopupChromeClient : public EmptyChromeClient {
59     WTF_MAKE_NONCOPYABLE(PagePopupChromeClient);
60     WTF_MAKE_FAST_ALLOCATED;
61
62 public:
63     explicit PagePopupChromeClient(WebPagePopupImpl* popup)
64         : m_popup(popup)
65     {
66         ASSERT(m_popup->widgetClient());
67     }
68
69 private:
70     virtual void closeWindowSoon() OVERRIDE
71     {
72         m_popup->closePopup();
73     }
74
75     virtual FloatRect windowRect() OVERRIDE
76     {
77         return FloatRect(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y, m_popup->m_windowRectInScreen.width, m_popup->m_windowRectInScreen.height);
78     }
79
80     virtual void setWindowRect(const FloatRect& rect) OVERRIDE
81     {
82         m_popup->m_windowRectInScreen = IntRect(rect);
83         m_popup->widgetClient()->setWindowRect(m_popup->m_windowRectInScreen);
84     }
85
86     virtual void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String&, const String&) OVERRIDE
87     {
88 #ifndef NDEBUG
89         fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber, message.utf8().data());
90 #endif
91     }
92
93     virtual void invalidateContentsAndRootView(const IntRect& paintRect) OVERRIDE
94     {
95         if (paintRect.isEmpty())
96             return;
97         m_popup->widgetClient()->didInvalidateRect(paintRect);
98     }
99
100     virtual void scroll(const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect) OVERRIDE
101     {
102         m_popup->widgetClient()->didScrollRect(scrollDelta.width(), scrollDelta.height(), intersection(scrollRect, clipRect));
103     }
104
105     virtual void invalidateContentsForSlowScroll(const IntRect& updateRect) OVERRIDE
106     {
107         invalidateContentsAndRootView(updateRect);
108     }
109
110     virtual void scheduleAnimation() OVERRIDE
111     {
112         m_popup->widgetClient()->scheduleAnimation();
113     }
114
115     virtual WebScreenInfo screenInfo() const OVERRIDE
116     {
117         return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
118     }
119
120     virtual void* webView() const OVERRIDE
121     {
122         return m_popup->m_webView;
123     }
124
125     virtual FloatSize minimumWindowSize() const OVERRIDE
126     {
127         return FloatSize(0, 0);
128     }
129
130     virtual void setCursor(const WebCore::Cursor& cursor) OVERRIDE
131     {
132         if (m_popup->m_webView->client())
133             m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor));
134     }
135
136     virtual void needTouchEvents(bool needsTouchEvents) OVERRIDE
137     {
138         m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
139     }
140
141     virtual GraphicsLayerFactory* graphicsLayerFactory() const OVERRIDE
142     {
143         return m_popup->m_webView->graphicsLayerFactory();
144     }
145
146     virtual void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer) OVERRIDE
147     {
148         m_popup->setRootGraphicsLayer(graphicsLayer);
149     }
150
151     WebPagePopupImpl* m_popup;
152 };
153
154 class PagePopupFeaturesClient : public ContextFeaturesClient {
155     virtual bool isEnabled(Document*, ContextFeatures::FeatureType, bool) OVERRIDE;
156 };
157
158 bool PagePopupFeaturesClient::isEnabled(Document*, ContextFeatures::FeatureType type, bool defaultValue)
159 {
160     if (type == ContextFeatures::PagePopup)
161         return true;
162     return defaultValue;
163 }
164
165 // WebPagePopupImpl ----------------------------------------------------------------
166
167 WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
168     : m_widgetClient(client)
169     , m_closing(false)
170     , m_layerTreeView(0)
171     , m_rootLayer(0)
172     , m_rootGraphicsLayer(0)
173     , m_isAcceleratedCompositingActive(false)
174 {
175     ASSERT(client);
176 }
177
178 WebPagePopupImpl::~WebPagePopupImpl()
179 {
180     ASSERT(!m_page);
181 }
182
183 bool WebPagePopupImpl::initialize(WebViewImpl* webView, PagePopupClient* popupClient, const IntRect&)
184 {
185     ASSERT(webView);
186     ASSERT(popupClient);
187     m_webView = webView;
188     m_popupClient = popupClient;
189
190     resize(m_popupClient->contentSize());
191
192     if (!initializePage())
193         return false;
194     m_widgetClient->show(WebNavigationPolicy());
195     setFocus(true);
196
197     return true;
198 }
199
200 bool WebPagePopupImpl::initializePage()
201 {
202     Page::PageClients pageClients;
203     fillWithEmptyClients(pageClients);
204     m_chromeClient = adoptPtr(new PagePopupChromeClient(this));
205     pageClients.chromeClient = m_chromeClient.get();
206
207     m_page = adoptPtr(new Page(pageClients));
208     m_page->settings().setScriptEnabled(true);
209     m_page->settings().setAllowScriptsToCloseWindows(true);
210     m_page->setDeviceScaleFactor(m_webView->deviceScaleFactor());
211     m_page->settings().setDeviceSupportsTouch(m_webView->page()->settings().deviceSupportsTouch());
212
213     static ContextFeaturesClient* pagePopupFeaturesClient =  new PagePopupFeaturesClient();
214     provideContextFeaturesTo(*m_page, pagePopupFeaturesClient);
215     static FrameLoaderClient* emptyFrameLoaderClient =  new EmptyFrameLoaderClient();
216     RefPtr<LocalFrame> frame = LocalFrame::create(emptyFrameLoaderClient, &m_page->frameHost(), 0);
217     frame->setView(FrameView::create(frame.get()));
218     frame->init();
219     frame->view()->resize(m_popupClient->contentSize());
220     frame->view()->setTransparent(false);
221
222     ASSERT(frame->domWindow());
223     DOMWindowPagePopup::install(*frame->domWindow(), m_popupClient);
224
225     RefPtr<SharedBuffer> data = SharedBuffer::create();
226     m_popupClient->writeDocument(data.get());
227     frame->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
228     return true;
229 }
230
231 void WebPagePopupImpl::destroyPage()
232 {
233     if (!m_page)
234         return;
235
236     if (m_page->mainFrame())
237         m_page->mainFrame()->loader().frameDetached();
238
239     m_page.clear();
240 }
241
242 void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer)
243 {
244     m_rootGraphicsLayer = layer;
245     m_rootLayer = layer ? layer->platformLayer() : 0;
246
247     setIsAcceleratedCompositingActive(layer);
248     if (m_layerTreeView) {
249         if (m_rootLayer) {
250             m_layerTreeView->setRootLayer(*m_rootLayer);
251         } else {
252             m_layerTreeView->clearRootLayer();
253         }
254     }
255 }
256
257 void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter)
258 {
259     if (m_isAcceleratedCompositingActive == enter)
260         return;
261
262     if (!enter) {
263         m_isAcceleratedCompositingActive = false;
264         m_widgetClient->didDeactivateCompositor();
265     } else if (m_layerTreeView) {
266         m_isAcceleratedCompositingActive = true;
267         m_widgetClient->didActivateCompositor(0);
268     } else {
269         TRACE_EVENT0("webkit", "WebPagePopupImpl::setIsAcceleratedCompositingActive(true)");
270
271         m_widgetClient->initializeLayerTreeView();
272         m_layerTreeView = m_widgetClient->layerTreeView();
273         if (m_layerTreeView) {
274             m_layerTreeView->setVisible(true);
275             m_widgetClient->didActivateCompositor(0);
276             m_isAcceleratedCompositingActive = true;
277             m_layerTreeView->setDeviceScaleFactor(m_widgetClient->deviceScaleFactor());
278         } else {
279             m_isAcceleratedCompositingActive = false;
280             m_widgetClient->didDeactivateCompositor();
281         }
282     }
283 }
284
285 WebSize WebPagePopupImpl::size()
286 {
287     return m_popupClient->contentSize();
288 }
289
290 void WebPagePopupImpl::animate(double)
291 {
292     PageWidgetDelegate::animate(m_page.get(), monotonicallyIncreasingTime());
293 }
294
295 void WebPagePopupImpl::enterForceCompositingMode(bool enter)
296 {
297     if (!m_page)
298         return;
299     if (m_page->settings().forceCompositingMode() == enter)
300         return;
301
302     TRACE_EVENT1("webkit", "WebPagePopupImpl::enterForceCompositingMode", "enter", enter);
303     m_page->settings().setForceCompositingMode(enter);
304     if (enter) {
305         LocalFrame* mainFrame = m_page->mainFrame();
306         if (!mainFrame)
307             return;
308         mainFrame->view()->updateCompositingLayersAfterStyleChange();
309     }
310 }
311
312 void WebPagePopupImpl::didExitCompositingMode()
313 {
314     setIsAcceleratedCompositingActive(false);
315     m_widgetClient->didInvalidateRect(IntRect(0, 0, size().width, size().height));
316     if (m_page)
317         m_page->mainFrame()->document()->setNeedsStyleRecalc(SubtreeStyleChange);
318 }
319
320 void WebPagePopupImpl::willCloseLayerTreeView()
321 {
322     setIsAcceleratedCompositingActive(false);
323     m_layerTreeView = 0;
324 }
325
326 void WebPagePopupImpl::layout()
327 {
328     PageWidgetDelegate::layout(m_page.get());
329 }
330
331 void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions)
332 {
333     if (!m_closing)
334         PageWidgetDelegate::paint(m_page.get(), 0, canvas, rect, PageWidgetDelegate::Opaque);
335 }
336
337 void WebPagePopupImpl::resize(const WebSize& newSize)
338 {
339     m_windowRectInScreen = WebRect(m_windowRectInScreen.x, m_windowRectInScreen.y, newSize.width, newSize.height);
340     m_widgetClient->setWindowRect(m_windowRectInScreen);
341
342     if (m_page)
343         m_page->mainFrame()->view()->resize(newSize);
344     m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
345 }
346
347 bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent&)
348 {
349     // The main WebView receives key events and forward them to this via handleKeyEvent().
350     ASSERT_NOT_REACHED();
351     return false;
352 }
353
354 bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent&)
355 {
356     // The main WebView receives key events and forward them to this via handleKeyEvent().
357     ASSERT_NOT_REACHED();
358     return false;
359 }
360
361 bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
362 {
363     if (m_closing || !m_page || !m_page->mainFrame() || !m_page->mainFrame()->view())
364         return false;
365     LocalFrame& frame = *m_page->mainFrame();
366     return frame.eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
367 }
368
369 bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
370 {
371     if (m_closing)
372         return false;
373     return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, event);
374 }
375
376 bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
377 {
378     if (m_closing || !m_page->mainFrame() || !m_page->mainFrame()->view())
379         return false;
380     return m_page->mainFrame()->eventHandler().keyEvent(event);
381 }
382
383 void WebPagePopupImpl::setFocus(bool enable)
384 {
385     if (!m_page)
386         return;
387     m_page->focusController().setFocused(enable);
388     if (enable)
389         m_page->focusController().setActive(true);
390 }
391
392 void WebPagePopupImpl::close()
393 {
394     m_closing = true;
395     destroyPage(); // In case closePopup() was not called.
396     m_widgetClient = 0;
397     deref();
398 }
399
400 void WebPagePopupImpl::closePopup()
401 {
402     if (m_page) {
403         m_page->mainFrame()->loader().stopAllLoaders();
404         ASSERT(m_page->mainFrame()->domWindow());
405         DOMWindowPagePopup::uninstall(*m_page->mainFrame()->domWindow());
406     }
407     m_closing = true;
408
409     destroyPage();
410
411     // m_widgetClient might be 0 because this widget might be already closed.
412     if (m_widgetClient) {
413         // closeWidgetSoon() will call this->close() later.
414         m_widgetClient->closeWidgetSoon();
415     }
416
417     m_popupClient->didClosePopup();
418 }
419
420 // WebPagePopup ----------------------------------------------------------------
421
422 WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
423 {
424     if (!client)
425         CRASH();
426     // A WebPagePopupImpl instance usually has two references.
427     //  - One owned by the instance itself. It represents the visible widget.
428     //  - One owned by a WebViewImpl. It's released when the WebViewImpl ask the
429     //    WebPagePopupImpl to close.
430     // We need them because the closing operation is asynchronous and the widget
431     // can be closed while the WebViewImpl is unaware of it.
432     return adoptRef(new WebPagePopupImpl(client)).leakRef();
433 }
434
435 } // namespace blink