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 "web/WebPagePopupImpl.h"
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"
62 class PagePopupChromeClient : public EmptyChromeClient {
63 WTF_MAKE_NONCOPYABLE(PagePopupChromeClient);
64 WTF_MAKE_FAST_ALLOCATED;
67 explicit PagePopupChromeClient(WebPagePopupImpl* popup)
70 ASSERT(m_popup->widgetClient());
74 virtual void closeWindowSoon() override
76 m_popup->closePopup();
79 virtual FloatRect windowRect() override
81 return FloatRect(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y, m_popup->m_windowRectInScreen.width, m_popup->m_windowRectInScreen.height);
84 virtual void setWindowRect(const FloatRect& rect) override
86 m_popup->m_windowRectInScreen = IntRect(rect);
87 m_popup->widgetClient()->setWindowRect(m_popup->m_windowRectInScreen);
90 virtual IntRect rootViewToScreen(const IntRect& rect) const override
92 IntRect rectInScreen(rect);
93 rectInScreen.move(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y);
97 virtual void addMessageToConsole(LocalFrame*, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String&, const String&) override
100 fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber, message.utf8().data());
104 virtual void invalidateContentsAndRootView(const IntRect& paintRect) override
106 if (paintRect.isEmpty())
108 m_popup->widgetClient()->didInvalidateRect(paintRect);
111 virtual void invalidateContentsForSlowScroll(const IntRect& updateRect) override
113 invalidateContentsAndRootView(updateRect);
116 virtual void scheduleAnimation() override
118 // Calling scheduleAnimation on m_webView so WebTestProxy will call beginFrame.
119 if (LayoutTestSupport::isRunningLayoutTest())
120 m_popup->m_webView->scheduleAnimation();
122 if (m_popup->isAcceleratedCompositingActive()) {
123 ASSERT(m_popup->m_layerTreeView);
124 m_popup->m_layerTreeView->setNeedsAnimate();
127 m_popup->m_widgetClient->scheduleAnimation();
130 virtual WebScreenInfo screenInfo() const override
132 return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
135 virtual void* webView() const override
137 return m_popup->m_webView;
140 virtual FloatSize minimumWindowSize() const override
142 return FloatSize(0, 0);
145 virtual void setCursor(const Cursor& cursor) override
147 if (m_popup->m_webView->client())
148 m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor));
151 virtual void needTouchEvents(bool needsTouchEvents) override
153 m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
156 virtual GraphicsLayerFactory* graphicsLayerFactory() const override
158 return m_popup->m_webView->graphicsLayerFactory();
161 virtual void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer) override
163 m_popup->setRootGraphicsLayer(graphicsLayer);
166 virtual void postAccessibilityNotification(AXObject* obj, AXObjectCache::AXNotification notification) override
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));
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));
177 WebPagePopupImpl* m_popup;
180 class PagePopupFeaturesClient : public ContextFeaturesClient {
181 virtual bool isEnabled(Document*, ContextFeatures::FeatureType, bool) override;
184 bool PagePopupFeaturesClient::isEnabled(Document*, ContextFeatures::FeatureType type, bool defaultValue)
186 if (type == ContextFeatures::PagePopup)
191 // WebPagePopupImpl ----------------------------------------------------------------
193 WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
194 : m_widgetClient(client)
198 , m_rootGraphicsLayer(0)
199 , m_isAcceleratedCompositingActive(false)
204 WebPagePopupImpl::~WebPagePopupImpl()
209 bool WebPagePopupImpl::initialize(WebViewImpl* webView, PagePopupClient* popupClient, const IntRect&)
214 m_popupClient = popupClient;
216 resize(m_popupClient->contentSize());
218 if (!m_widgetClient || !initializePage())
220 m_widgetClient->show(WebNavigationPolicy());
226 bool WebPagePopupImpl::initializePage()
228 Page::PageClients pageClients;
229 fillWithEmptyClients(pageClients);
230 m_chromeClient = adoptPtr(new PagePopupChromeClient(this));
231 pageClients.chromeClient = m_chromeClient.get();
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());
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()));
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());
252 ASSERT(frame->domWindow());
253 DOMWindowPagePopup::install(*frame->domWindow(), m_popupClient);
254 ASSERT(m_popupClient->ownerElement().document().existingAXObjectCache() == frame->document()->existingAXObjectCache());
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)));
262 void WebPagePopupImpl::destroyPage()
267 m_page->willBeDestroyed();
271 AXObject* WebPagePopupImpl::rootAXObject()
273 if (!m_page || !m_page->mainFrame())
275 Document* document = toLocalFrame(m_page->mainFrame())->document();
278 AXObjectCache* cache = document->axObjectCache();
280 return cache->getOrCreateAXObjectFromRenderView(document->renderView());
283 void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer)
285 m_rootGraphicsLayer = layer;
286 m_rootLayer = layer ? layer->platformLayer() : 0;
288 setIsAcceleratedCompositingActive(layer);
289 if (m_layerTreeView) {
291 m_layerTreeView->setRootLayer(*m_rootLayer);
293 m_layerTreeView->clearRootLayer();
298 void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter)
300 if (m_isAcceleratedCompositingActive == enter)
304 m_isAcceleratedCompositingActive = false;
305 } else if (m_layerTreeView) {
306 m_isAcceleratedCompositingActive = true;
308 TRACE_EVENT0("blink", "WebPagePopupImpl::setIsAcceleratedCompositingActive(true)");
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());
317 m_isAcceleratedCompositingActive = false;
322 WebSize WebPagePopupImpl::size()
324 return m_popupClient->contentSize();
327 void WebPagePopupImpl::beginFrame(const WebBeginFrameArgs& frameTime)
331 // FIXME: This should use frameTime.lastFrameTimeMonotonic but doing so
333 PageWidgetDelegate::animate(*m_page, monotonicallyIncreasingTime(), *m_page->deprecatedLocalMainFrame());
336 void WebPagePopupImpl::willCloseLayerTreeView()
338 setIsAcceleratedCompositingActive(false);
342 void WebPagePopupImpl::layout()
346 PageWidgetDelegate::layout(*m_page, *m_page->deprecatedLocalMainFrame());
349 void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect)
352 PageWidgetDelegate::paint(*m_page, 0, canvas, rect, PageWidgetDelegate::Opaque, *m_page->deprecatedLocalMainFrame());
355 void WebPagePopupImpl::resize(const WebSize& newSize)
357 m_windowRectInScreen = WebRect(m_windowRectInScreen.x, m_windowRectInScreen.y, newSize.width, newSize.height);
358 m_widgetClient->setWindowRect(m_windowRectInScreen);
361 toLocalFrame(m_page->mainFrame())->view()->resize(newSize);
362 m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
365 bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent&)
367 // The main WebView receives key events and forward them to this via handleKeyEvent().
368 ASSERT_NOT_REACHED();
372 bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent&)
374 // The main WebView receives key events and forward them to this via handleKeyEvent().
375 ASSERT_NOT_REACHED();
379 bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
381 if (m_closing || !m_page || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
383 LocalFrame& frame = *toLocalFrame(m_page->mainFrame());
384 return frame.eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
387 bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
391 return PageWidgetDelegate::handleInputEvent(*this, event, m_page->deprecatedLocalMainFrame());
394 bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
396 if (m_closing || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
398 return toLocalFrame(m_page->mainFrame())->eventHandler().keyEvent(event);
401 void WebPagePopupImpl::setFocus(bool enable)
405 m_page->focusController().setFocused(enable);
407 m_page->focusController().setActive(true);
410 void WebPagePopupImpl::close()
413 destroyPage(); // In case closePopup() was not called.
418 void WebPagePopupImpl::closePopup()
421 toLocalFrame(m_page->mainFrame())->loader().stopAllLoaders();
422 ASSERT(m_page->mainFrame()->domWindow());
423 DOMWindowPagePopup::uninstall(*m_page->mainFrame()->domWindow());
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();
435 m_popupClient->didClosePopup();
438 LocalDOMWindow* WebPagePopupImpl::window()
440 return m_page->mainFrame()->domWindow();
443 void WebPagePopupImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
445 ASSERT(isAcceleratedCompositingActive());
446 m_layerTreeView->compositeAndReadbackAsync(callback);
449 WebPoint WebPagePopupImpl::positionRelativeToOwner()
451 WebRect windowRect = m_webView->client()->rootWindowRect();
452 return WebPoint(m_windowRectInScreen.x - windowRect.x, m_windowRectInScreen.y - windowRect.y);
455 // WebPagePopup ----------------------------------------------------------------
457 WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
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();