Update To 11.40.268.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 "web/WebPagePopupImpl.h"
33
34 #include "core/dom/ContextFeatures.h"
35 #include "core/frame/FrameView.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/frame/Settings.h"
38 #include "core/loader/EmptyClients.h"
39 #include "core/loader/FrameLoadRequest.h"
40 #include "core/page/Chrome.h"
41 #include "core/page/DOMWindowPagePopup.h"
42 #include "core/page/EventHandler.h"
43 #include "core/page/FocusController.h"
44 #include "core/page/Page.h"
45 #include "core/page/PagePopupClient.h"
46 #include "platform/LayoutTestSupport.h"
47 #include "platform/TraceEvent.h"
48 #include "platform/heap/Handle.h"
49 #include "public/platform/WebCompositeAndReadbackAsyncCallback.h"
50 #include "public/platform/WebCursorInfo.h"
51 #include "public/web/WebAXObject.h"
52 #include "public/web/WebFrameClient.h"
53 #include "public/web/WebViewClient.h"
54 #include "public/web/WebWidgetClient.h"
55 #include "web/WebInputEventConversion.h"
56 #include "web/WebLocalFrameImpl.h"
57 #include "web/WebSettingsImpl.h"
58 #include "web/WebViewImpl.h"
59
60 namespace blink {
61
62 class PagePopupChromeClient : public EmptyChromeClient {
63     WTF_MAKE_NONCOPYABLE(PagePopupChromeClient);
64     WTF_MAKE_FAST_ALLOCATED;
65
66 public:
67     explicit PagePopupChromeClient(WebPagePopupImpl* popup)
68         : m_popup(popup)
69     {
70         ASSERT(m_popup->widgetClient());
71     }
72
73 private:
74     virtual void closeWindowSoon() override
75     {
76         m_popup->closePopup();
77     }
78
79     virtual FloatRect windowRect() override
80     {
81         return FloatRect(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y, m_popup->m_windowRectInScreen.width, m_popup->m_windowRectInScreen.height);
82     }
83
84     virtual void setWindowRect(const FloatRect& rect) override
85     {
86         m_popup->m_windowRectInScreen = IntRect(rect);
87         m_popup->widgetClient()->setWindowRect(m_popup->m_windowRectInScreen);
88     }
89
90     virtual IntRect rootViewToScreen(const IntRect& rect) const override
91     {
92         IntRect rectInScreen(rect);
93         rectInScreen.move(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y);
94         return rectInScreen;
95     }
96
97     virtual void addMessageToConsole(LocalFrame*, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String&, const String&) override
98     {
99 #ifndef NDEBUG
100         fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber, message.utf8().data());
101 #endif
102     }
103
104     virtual void invalidateContentsAndRootView(const IntRect& paintRect) override
105     {
106         if (paintRect.isEmpty())
107             return;
108         m_popup->widgetClient()->didInvalidateRect(paintRect);
109     }
110
111     virtual void invalidateContentsForSlowScroll(const IntRect& updateRect) override
112     {
113         invalidateContentsAndRootView(updateRect);
114     }
115
116     virtual void scheduleAnimation() override
117     {
118         // Calling scheduleAnimation on m_webView so WebTestProxy will call beginFrame.
119         if (LayoutTestSupport::isRunningLayoutTest())
120             m_popup->m_webView->scheduleAnimation();
121
122         if (m_popup->isAcceleratedCompositingActive()) {
123             ASSERT(m_popup->m_layerTreeView);
124             m_popup->m_layerTreeView->setNeedsAnimate();
125             return;
126         }
127         m_popup->m_widgetClient->scheduleAnimation();
128     }
129
130     virtual WebScreenInfo screenInfo() const override
131     {
132         return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
133     }
134
135     virtual void* webView() const override
136     {
137         return m_popup->m_webView;
138     }
139
140     virtual FloatSize minimumWindowSize() const override
141     {
142         return FloatSize(0, 0);
143     }
144
145     virtual void setCursor(const Cursor& cursor) override
146     {
147         if (m_popup->m_webView->client())
148             m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor));
149     }
150
151     virtual void needTouchEvents(bool needsTouchEvents) override
152     {
153         m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
154     }
155
156     virtual GraphicsLayerFactory* graphicsLayerFactory() const override
157     {
158         return m_popup->m_webView->graphicsLayerFactory();
159     }
160
161     virtual void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer) override
162     {
163         m_popup->setRootGraphicsLayer(graphicsLayer);
164     }
165
166     virtual void postAccessibilityNotification(AXObject* obj, AXObjectCache::AXNotification notification) override
167     {
168         WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(m_popup->m_popupClient->ownerElement().document().frame());
169         if (obj && frame && frame->client())
170             frame->client()->postAccessibilityEvent(WebAXObject(obj), static_cast<WebAXEvent>(notification));
171
172         // FIXME: Delete these lines once Chromium only uses the frame client interface, above.
173         if (obj && m_popup->m_webView->client())
174             m_popup->m_webView->client()->postAccessibilityEvent(WebAXObject(obj), static_cast<WebAXEvent>(notification));
175     }
176
177     WebPagePopupImpl* m_popup;
178 };
179
180 class PagePopupFeaturesClient : public ContextFeaturesClient {
181     virtual bool isEnabled(Document*, ContextFeatures::FeatureType, bool) override;
182 };
183
184 bool PagePopupFeaturesClient::isEnabled(Document*, ContextFeatures::FeatureType type, bool defaultValue)
185 {
186     if (type == ContextFeatures::PagePopup)
187         return true;
188     return defaultValue;
189 }
190
191 // WebPagePopupImpl ----------------------------------------------------------------
192
193 WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
194     : m_widgetClient(client)
195     , m_closing(false)
196     , m_layerTreeView(0)
197     , m_rootLayer(0)
198     , m_rootGraphicsLayer(0)
199     , m_isAcceleratedCompositingActive(false)
200 {
201     ASSERT(client);
202 }
203
204 WebPagePopupImpl::~WebPagePopupImpl()
205 {
206     ASSERT(!m_page);
207 }
208
209 bool WebPagePopupImpl::initialize(WebViewImpl* webView, PagePopupClient* popupClient, const IntRect&)
210 {
211     ASSERT(webView);
212     ASSERT(popupClient);
213     m_webView = webView;
214     m_popupClient = popupClient;
215
216     resize(m_popupClient->contentSize());
217
218     if (!m_widgetClient || !initializePage())
219         return false;
220     m_widgetClient->show(WebNavigationPolicy());
221     setFocus(true);
222
223     return true;
224 }
225
226 bool WebPagePopupImpl::initializePage()
227 {
228     Page::PageClients pageClients;
229     fillWithEmptyClients(pageClients);
230     m_chromeClient = adoptPtr(new PagePopupChromeClient(this));
231     pageClients.chromeClient = m_chromeClient.get();
232
233     m_page = adoptPtrWillBeNoop(new Page(pageClients));
234     m_page->settings().setScriptEnabled(true);
235     m_page->settings().setAllowScriptsToCloseWindows(true);
236     m_page->setDeviceScaleFactor(m_webView->deviceScaleFactor());
237     m_page->settings().setDeviceSupportsTouch(m_webView->page()->settings().deviceSupportsTouch());
238     // FIXME: Should we support enabling a11y while a popup is shown?
239     m_page->settings().setAccessibilityEnabled(m_webView->page()->settings().accessibilityEnabled());
240
241     provideContextFeaturesTo(*m_page, adoptPtr(new PagePopupFeaturesClient()));
242     static FrameLoaderClient* emptyFrameLoaderClient = new EmptyFrameLoaderClient();
243     RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(emptyFrameLoaderClient, &m_page->frameHost(), 0);
244     frame->setPagePopupOwner(m_popupClient->ownerElement());
245     frame->setView(FrameView::create(frame.get()));
246     frame->init();
247     frame->view()->resize(m_popupClient->contentSize());
248     frame->view()->setTransparent(false);
249     if (AXObjectCache* cache = m_popupClient->ownerElement().document().existingAXObjectCache())
250         cache->childrenChanged(&m_popupClient->ownerElement());
251
252     ASSERT(frame->domWindow());
253     DOMWindowPagePopup::install(*frame->domWindow(), m_popupClient);
254     ASSERT(m_popupClient->ownerElement().document().existingAXObjectCache() == frame->document()->existingAXObjectCache());
255
256     RefPtr<SharedBuffer> data = SharedBuffer::create();
257     m_popupClient->writeDocument(data.get());
258     frame->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
259     return true;
260 }
261
262 void WebPagePopupImpl::destroyPage()
263 {
264     if (!m_page)
265         return;
266
267     m_page->willBeDestroyed();
268     m_page.clear();
269 }
270
271 AXObject* WebPagePopupImpl::rootAXObject()
272 {
273     if (!m_page || !m_page->mainFrame())
274         return 0;
275     Document* document = toLocalFrame(m_page->mainFrame())->document();
276     if (!document)
277         return 0;
278     AXObjectCache* cache = document->axObjectCache();
279     ASSERT(cache);
280     return cache->getOrCreateAXObjectFromRenderView(document->renderView());
281 }
282
283 void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer)
284 {
285     m_rootGraphicsLayer = layer;
286     m_rootLayer = layer ? layer->platformLayer() : 0;
287
288     setIsAcceleratedCompositingActive(layer);
289     if (m_layerTreeView) {
290         if (m_rootLayer) {
291             m_layerTreeView->setRootLayer(*m_rootLayer);
292         } else {
293             m_layerTreeView->clearRootLayer();
294         }
295     }
296 }
297
298 void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter)
299 {
300     if (m_isAcceleratedCompositingActive == enter)
301         return;
302
303     if (!enter) {
304         m_isAcceleratedCompositingActive = false;
305     } else if (m_layerTreeView) {
306         m_isAcceleratedCompositingActive = true;
307     } else {
308         TRACE_EVENT0("blink", "WebPagePopupImpl::setIsAcceleratedCompositingActive(true)");
309
310         m_widgetClient->initializeLayerTreeView();
311         m_layerTreeView = m_widgetClient->layerTreeView();
312         if (m_layerTreeView) {
313             m_layerTreeView->setVisible(true);
314             m_isAcceleratedCompositingActive = true;
315             m_layerTreeView->setDeviceScaleFactor(m_widgetClient->deviceScaleFactor());
316         } else {
317             m_isAcceleratedCompositingActive = false;
318         }
319     }
320 }
321
322 WebSize WebPagePopupImpl::size()
323 {
324     return m_popupClient->contentSize();
325 }
326
327 void WebPagePopupImpl::beginFrame(const WebBeginFrameArgs& frameTime)
328 {
329     if (!m_page)
330         return;
331     // FIXME: This should use frameTime.lastFrameTimeMonotonic but doing so
332     // breaks tests.
333     PageWidgetDelegate::animate(*m_page, monotonicallyIncreasingTime(), *m_page->deprecatedLocalMainFrame());
334 }
335
336 void WebPagePopupImpl::willCloseLayerTreeView()
337 {
338     setIsAcceleratedCompositingActive(false);
339     m_layerTreeView = 0;
340 }
341
342 void WebPagePopupImpl::layout()
343 {
344     if (!m_page)
345         return;
346     PageWidgetDelegate::layout(*m_page, *m_page->deprecatedLocalMainFrame());
347 }
348
349 void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect)
350 {
351     if (!m_closing)
352         PageWidgetDelegate::paint(*m_page, 0, canvas, rect, PageWidgetDelegate::Opaque, *m_page->deprecatedLocalMainFrame());
353 }
354
355 void WebPagePopupImpl::resize(const WebSize& newSize)
356 {
357     m_windowRectInScreen = WebRect(m_windowRectInScreen.x, m_windowRectInScreen.y, newSize.width, newSize.height);
358     m_widgetClient->setWindowRect(m_windowRectInScreen);
359
360     if (m_page)
361         toLocalFrame(m_page->mainFrame())->view()->resize(newSize);
362     m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
363 }
364
365 bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent&)
366 {
367     // The main WebView receives key events and forward them to this via handleKeyEvent().
368     ASSERT_NOT_REACHED();
369     return false;
370 }
371
372 bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent&)
373 {
374     // The main WebView receives key events and forward them to this via handleKeyEvent().
375     ASSERT_NOT_REACHED();
376     return false;
377 }
378
379 bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
380 {
381     if (m_closing || !m_page || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
382         return false;
383     LocalFrame& frame = *toLocalFrame(m_page->mainFrame());
384     return frame.eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
385 }
386
387 bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
388 {
389     if (m_closing)
390         return false;
391     return PageWidgetDelegate::handleInputEvent(*this, event, m_page->deprecatedLocalMainFrame());
392 }
393
394 bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
395 {
396     if (m_closing || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
397         return false;
398     return toLocalFrame(m_page->mainFrame())->eventHandler().keyEvent(event);
399 }
400
401 void WebPagePopupImpl::setFocus(bool enable)
402 {
403     if (!m_page)
404         return;
405     m_page->focusController().setFocused(enable);
406     if (enable)
407         m_page->focusController().setActive(true);
408 }
409
410 void WebPagePopupImpl::close()
411 {
412     m_closing = true;
413     destroyPage(); // In case closePopup() was not called.
414     m_widgetClient = 0;
415     deref();
416 }
417
418 void WebPagePopupImpl::closePopup()
419 {
420     if (m_page) {
421         toLocalFrame(m_page->mainFrame())->loader().stopAllLoaders();
422         ASSERT(m_page->mainFrame()->domWindow());
423         DOMWindowPagePopup::uninstall(*m_page->mainFrame()->domWindow());
424     }
425     m_closing = true;
426
427     destroyPage();
428
429     // m_widgetClient might be 0 because this widget might be already closed.
430     if (m_widgetClient) {
431         // closeWidgetSoon() will call this->close() later.
432         m_widgetClient->closeWidgetSoon();
433     }
434
435     m_popupClient->didClosePopup();
436 }
437
438 LocalDOMWindow* WebPagePopupImpl::window()
439 {
440     return m_page->mainFrame()->domWindow();
441 }
442
443 void WebPagePopupImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
444 {
445     ASSERT(isAcceleratedCompositingActive());
446     m_layerTreeView->compositeAndReadbackAsync(callback);
447 }
448
449 WebPoint WebPagePopupImpl::positionRelativeToOwner()
450 {
451     WebRect windowRect = m_webView->client()->rootWindowRect();
452     return WebPoint(m_windowRectInScreen.x - windowRect.x, m_windowRectInScreen.y - windowRect.y);
453 }
454
455 // WebPagePopup ----------------------------------------------------------------
456
457 WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
458 {
459     if (!client)
460         CRASH();
461     // A WebPagePopupImpl instance usually has two references.
462     //  - One owned by the instance itself. It represents the visible widget.
463     //  - One owned by a WebViewImpl. It's released when the WebViewImpl ask the
464     //    WebPagePopupImpl to close.
465     // We need them because the closing operation is asynchronous and the widget
466     // can be closed while the WebViewImpl is unaware of it.
467     return adoptRef(new WebPagePopupImpl(client)).leakRef();
468 }
469
470 } // namespace blink