2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
32 #include "WebPagePopupImpl.h"
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"
53 using namespace WebCore;
58 class PagePopupChromeClient : public EmptyChromeClient {
59 WTF_MAKE_NONCOPYABLE(PagePopupChromeClient);
60 WTF_MAKE_FAST_ALLOCATED;
63 explicit PagePopupChromeClient(WebPagePopupImpl* popup)
66 ASSERT(m_popup->widgetClient());
70 virtual void closeWindowSoon() OVERRIDE
72 m_popup->closePopup();
75 virtual FloatRect windowRect() OVERRIDE
77 return FloatRect(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y, m_popup->m_windowRectInScreen.width, m_popup->m_windowRectInScreen.height);
80 virtual void setWindowRect(const FloatRect& rect) OVERRIDE
82 m_popup->m_windowRectInScreen = IntRect(rect);
83 m_popup->widgetClient()->setWindowRect(m_popup->m_windowRectInScreen);
86 virtual void addMessageToConsole(MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String&, const String&) OVERRIDE
89 fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber, message.utf8().data());
93 virtual void invalidateContentsAndRootView(const IntRect& paintRect) OVERRIDE
95 if (paintRect.isEmpty())
97 m_popup->widgetClient()->didInvalidateRect(paintRect);
100 virtual void scroll(const IntSize& scrollDelta, const IntRect& scrollRect, const IntRect& clipRect) OVERRIDE
102 m_popup->widgetClient()->didScrollRect(scrollDelta.width(), scrollDelta.height(), intersection(scrollRect, clipRect));
105 virtual void invalidateContentsForSlowScroll(const IntRect& updateRect) OVERRIDE
107 invalidateContentsAndRootView(updateRect);
110 virtual void scheduleAnimation() OVERRIDE
112 m_popup->widgetClient()->scheduleAnimation();
115 virtual WebScreenInfo screenInfo() const OVERRIDE
117 return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
120 virtual void* webView() const OVERRIDE
122 return m_popup->m_webView;
125 virtual FloatSize minimumWindowSize() const OVERRIDE
127 return FloatSize(0, 0);
130 virtual void setCursor(const WebCore::Cursor& cursor) OVERRIDE
132 if (m_popup->m_webView->client())
133 m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor));
136 virtual void needTouchEvents(bool needsTouchEvents) OVERRIDE
138 m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
141 virtual GraphicsLayerFactory* graphicsLayerFactory() const OVERRIDE
143 return m_popup->m_webView->graphicsLayerFactory();
146 virtual void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer) OVERRIDE
148 m_popup->setRootGraphicsLayer(graphicsLayer);
151 WebPagePopupImpl* m_popup;
154 class PagePopupFeaturesClient : public ContextFeaturesClient {
155 virtual bool isEnabled(Document*, ContextFeatures::FeatureType, bool) OVERRIDE;
158 bool PagePopupFeaturesClient::isEnabled(Document*, ContextFeatures::FeatureType type, bool defaultValue)
160 if (type == ContextFeatures::PagePopup)
165 // WebPagePopupImpl ----------------------------------------------------------------
167 WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
168 : m_widgetClient(client)
172 , m_rootGraphicsLayer(0)
173 , m_isAcceleratedCompositingActive(false)
178 WebPagePopupImpl::~WebPagePopupImpl()
183 bool WebPagePopupImpl::initialize(WebViewImpl* webView, PagePopupClient* popupClient, const IntRect&)
188 m_popupClient = popupClient;
190 resize(m_popupClient->contentSize());
192 if (!initializePage())
194 m_widgetClient->show(WebNavigationPolicy());
200 bool WebPagePopupImpl::initializePage()
202 Page::PageClients pageClients;
203 fillWithEmptyClients(pageClients);
204 m_chromeClient = adoptPtr(new PagePopupChromeClient(this));
205 pageClients.chromeClient = m_chromeClient.get();
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());
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()));
219 frame->view()->resize(m_popupClient->contentSize());
220 frame->view()->setTransparent(false);
222 ASSERT(frame->domWindow());
223 DOMWindowPagePopup::install(*frame->domWindow(), m_popupClient);
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)));
231 void WebPagePopupImpl::destroyPage()
236 if (m_page->mainFrame())
237 m_page->mainFrame()->loader().frameDetached();
242 void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer)
244 m_rootGraphicsLayer = layer;
245 m_rootLayer = layer ? layer->platformLayer() : 0;
247 setIsAcceleratedCompositingActive(layer);
248 if (m_layerTreeView) {
250 m_layerTreeView->setRootLayer(*m_rootLayer);
252 m_layerTreeView->clearRootLayer();
257 void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter)
259 if (m_isAcceleratedCompositingActive == enter)
263 m_isAcceleratedCompositingActive = false;
264 m_widgetClient->didDeactivateCompositor();
265 } else if (m_layerTreeView) {
266 m_isAcceleratedCompositingActive = true;
267 m_widgetClient->didActivateCompositor(0);
269 TRACE_EVENT0("webkit", "WebPagePopupImpl::setIsAcceleratedCompositingActive(true)");
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());
279 m_isAcceleratedCompositingActive = false;
280 m_widgetClient->didDeactivateCompositor();
285 WebSize WebPagePopupImpl::size()
287 return m_popupClient->contentSize();
290 void WebPagePopupImpl::animate(double)
292 PageWidgetDelegate::animate(m_page.get(), monotonicallyIncreasingTime());
295 void WebPagePopupImpl::enterForceCompositingMode(bool enter)
299 if (m_page->settings().forceCompositingMode() == enter)
302 TRACE_EVENT1("webkit", "WebPagePopupImpl::enterForceCompositingMode", "enter", enter);
303 m_page->settings().setForceCompositingMode(enter);
305 LocalFrame* mainFrame = m_page->mainFrame();
308 mainFrame->view()->updateCompositingLayersAfterStyleChange();
312 void WebPagePopupImpl::didExitCompositingMode()
314 setIsAcceleratedCompositingActive(false);
315 m_widgetClient->didInvalidateRect(IntRect(0, 0, size().width, size().height));
317 m_page->mainFrame()->document()->setNeedsStyleRecalc(SubtreeStyleChange);
320 void WebPagePopupImpl::willCloseLayerTreeView()
322 setIsAcceleratedCompositingActive(false);
326 void WebPagePopupImpl::layout()
328 PageWidgetDelegate::layout(m_page.get());
331 void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect, PaintOptions)
334 PageWidgetDelegate::paint(m_page.get(), 0, canvas, rect, PageWidgetDelegate::Opaque);
337 void WebPagePopupImpl::resize(const WebSize& newSize)
339 m_windowRectInScreen = WebRect(m_windowRectInScreen.x, m_windowRectInScreen.y, newSize.width, newSize.height);
340 m_widgetClient->setWindowRect(m_windowRectInScreen);
343 m_page->mainFrame()->view()->resize(newSize);
344 m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
347 bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent&)
349 // The main WebView receives key events and forward them to this via handleKeyEvent().
350 ASSERT_NOT_REACHED();
354 bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent&)
356 // The main WebView receives key events and forward them to this via handleKeyEvent().
357 ASSERT_NOT_REACHED();
361 bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
363 if (m_closing || !m_page || !m_page->mainFrame() || !m_page->mainFrame()->view())
365 LocalFrame& frame = *m_page->mainFrame();
366 return frame.eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
369 bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
373 return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, event);
376 bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
378 if (m_closing || !m_page->mainFrame() || !m_page->mainFrame()->view())
380 return m_page->mainFrame()->eventHandler().keyEvent(event);
383 void WebPagePopupImpl::setFocus(bool enable)
387 m_page->focusController().setFocused(enable);
389 m_page->focusController().setActive(true);
392 void WebPagePopupImpl::close()
395 destroyPage(); // In case closePopup() was not called.
400 void WebPagePopupImpl::closePopup()
403 m_page->mainFrame()->loader().stopAllLoaders();
404 ASSERT(m_page->mainFrame()->domWindow());
405 DOMWindowPagePopup::uninstall(*m_page->mainFrame()->domWindow());
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();
417 m_popupClient->didClosePopup();
420 // WebPagePopup ----------------------------------------------------------------
422 WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
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();