Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / web / WebPagePopupImpl.cpp
blob53e0a464e6ca52a3d7be8f081ba1ae8242ca46af
1 /*
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
6 * met:
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.
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.
31 #include "config.h"
32 #include "web/WebPagePopupImpl.h"
34 #include "core/dom/ContextFeatures.h"
35 #include "core/frame/FrameHost.h"
36 #include "core/frame/FrameView.h"
37 #include "core/frame/LocalFrame.h"
38 #include "core/frame/Settings.h"
39 #include "core/frame/VisualViewport.h"
40 #include "core/input/EventHandler.h"
41 #include "core/layout/LayoutView.h"
42 #include "core/loader/EmptyClients.h"
43 #include "core/loader/FrameLoadRequest.h"
44 #include "core/page/DOMWindowPagePopup.h"
45 #include "core/page/FocusController.h"
46 #include "core/page/Page.h"
47 #include "core/page/PagePopupClient.h"
48 #include "modules/accessibility/AXObject.h"
49 #include "modules/accessibility/AXObjectCacheImpl.h"
50 #include "platform/EventDispatchForbiddenScope.h"
51 #include "platform/LayoutTestSupport.h"
52 #include "platform/ScriptForbiddenScope.h"
53 #include "platform/TraceEvent.h"
54 #include "platform/heap/Handle.h"
55 #include "public/platform/WebCompositeAndReadbackAsyncCallback.h"
56 #include "public/platform/WebCursorInfo.h"
57 #include "public/web/WebAXObject.h"
58 #include "public/web/WebFrameClient.h"
59 #include "public/web/WebViewClient.h"
60 #include "public/web/WebWidgetClient.h"
61 #include "web/WebInputEventConversion.h"
62 #include "web/WebLocalFrameImpl.h"
63 #include "web/WebSettingsImpl.h"
64 #include "web/WebViewImpl.h"
66 namespace blink {
68 class PagePopupChromeClient final : public EmptyChromeClient {
69 public:
70 static PassOwnPtrWillBeRawPtr<PagePopupChromeClient> create(WebPagePopupImpl* popup)
72 return adoptPtrWillBeNoop(new PagePopupChromeClient(popup));
75 void setWindowRect(const IntRect& rect) override
77 m_popup->m_windowRectInScreen = rect;
78 m_popup->widgetClient()->setWindowRect(m_popup->m_windowRectInScreen);
81 private:
82 explicit PagePopupChromeClient(WebPagePopupImpl* popup)
83 : m_popup(popup)
85 ASSERT(m_popup->widgetClient());
88 void closeWindowSoon() override
90 m_popup->closePopup();
93 IntRect windowRect() override
95 return IntRect(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y, m_popup->m_windowRectInScreen.width, m_popup->m_windowRectInScreen.height);
98 IntRect viewportToScreen(const IntRect& rect) const override
100 IntRect rectInScreen(rect);
101 rectInScreen.move(m_popup->m_windowRectInScreen.x, m_popup->m_windowRectInScreen.y);
102 return rectInScreen;
105 void addMessageToConsole(LocalFrame*, MessageSource, MessageLevel, const String& message, unsigned lineNumber, const String&, const String&) override
107 #ifndef NDEBUG
108 fprintf(stderr, "CONSOLE MESSSAGE:%u: %s\n", lineNumber, message.utf8().data());
109 #endif
112 void invalidateRect(const IntRect& paintRect) override
114 if (!paintRect.isEmpty())
115 m_popup->widgetClient()->didInvalidateRect(paintRect);
118 void scheduleAnimation() override
120 // Calling scheduleAnimation on m_webView so WebTestProxy will call beginFrame.
121 if (LayoutTestSupport::isRunningLayoutTest())
122 m_popup->m_webView->scheduleAnimation();
124 if (m_popup->isAcceleratedCompositingActive()) {
125 ASSERT(m_popup->m_layerTreeView);
126 m_popup->m_layerTreeView->setNeedsCompositorUpdate();
127 return;
129 m_popup->m_widgetClient->scheduleAnimation();
132 WebScreenInfo screenInfo() const override
134 return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
137 void* webView() const override
139 return m_popup->m_webView;
142 IntSize minimumWindowSize() const override
144 return IntSize(0, 0);
147 void setCursor(const Cursor& cursor) override
149 if (m_popup->m_webView->client())
150 m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor));
153 void needTouchEvents(bool needsTouchEvents) override
155 m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
158 GraphicsLayerFactory* graphicsLayerFactory() const override
160 return m_popup->m_webView->graphicsLayerFactory();
163 void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer, LocalFrame* localRoot) override
165 m_popup->setRootGraphicsLayer(graphicsLayer);
168 void postAccessibilityNotification(AXObject* obj, AXObjectCache::AXNotification notification) override
170 WebLocalFrameImpl* frame = WebLocalFrameImpl::fromFrame(m_popup->m_popupClient->ownerElement().document().frame());
171 if (obj && frame && frame->client())
172 frame->client()->postAccessibilityEvent(WebAXObject(obj), static_cast<WebAXEvent>(notification));
175 void setToolTip(const String& tooltipText, TextDirection dir) override
177 if (m_popup->widgetClient())
178 m_popup->widgetClient()->setToolTipText(tooltipText, toWebTextDirection(dir));
181 WebPagePopupImpl* m_popup;
184 class PagePopupFeaturesClient : public ContextFeaturesClient {
185 bool isEnabled(Document*, ContextFeatures::FeatureType, bool) override;
188 bool PagePopupFeaturesClient::isEnabled(Document*, ContextFeatures::FeatureType type, bool defaultValue)
190 if (type == ContextFeatures::PagePopup)
191 return true;
192 return defaultValue;
195 // WebPagePopupImpl ----------------------------------------------------------------
197 WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
198 : m_widgetClient(client)
199 , m_closing(false)
200 , m_layerTreeView(0)
201 , m_rootLayer(0)
202 , m_rootGraphicsLayer(0)
203 , m_isAcceleratedCompositingActive(false)
205 ASSERT(client);
208 WebPagePopupImpl::~WebPagePopupImpl()
210 ASSERT(!m_page);
213 bool WebPagePopupImpl::initialize(WebViewImpl* webView, PagePopupClient* popupClient)
215 ASSERT(webView);
216 ASSERT(popupClient);
217 m_webView = webView;
218 m_popupClient = popupClient;
220 resize(m_popupClient->contentSize());
222 if (!m_widgetClient || !initializePage())
223 return false;
224 m_widgetClient->show(WebNavigationPolicy());
225 setFocus(true);
227 return true;
230 bool WebPagePopupImpl::initializePage()
232 Page::PageClients pageClients;
233 fillWithEmptyClients(pageClients);
234 m_chromeClient = PagePopupChromeClient::create(this);
235 pageClients.chromeClient = m_chromeClient.get();
237 m_page = adoptPtrWillBeNoop(new Page(pageClients));
238 m_page->settings().setScriptEnabled(true);
239 m_page->settings().setAllowScriptsToCloseWindows(true);
240 m_page->setDeviceScaleFactor(m_webView->deviceScaleFactor());
241 m_page->settings().setDeviceSupportsTouch(m_webView->page()->settings().deviceSupportsTouch());
242 // FIXME: Should we support enabling a11y while a popup is shown?
243 m_page->settings().setAccessibilityEnabled(m_webView->page()->settings().accessibilityEnabled());
244 m_page->settings().setScrollAnimatorEnabled(m_webView->page()->settings().scrollAnimatorEnabled());
246 provideContextFeaturesTo(*m_page, adoptPtr(new PagePopupFeaturesClient()));
247 DEFINE_STATIC_LOCAL(OwnPtrWillBePersistent<FrameLoaderClient>, emptyFrameLoaderClient, (EmptyFrameLoaderClient::create()));
248 RefPtrWillBeRawPtr<LocalFrame> frame = LocalFrame::create(emptyFrameLoaderClient.get(), &m_page->frameHost(), 0);
249 frame->setPagePopupOwner(m_popupClient->ownerElement());
250 frame->setView(FrameView::create(frame.get()));
251 frame->init();
252 frame->view()->resize(m_popupClient->contentSize());
253 frame->view()->setTransparent(false);
254 if (AXObjectCache* cache = m_popupClient->ownerElement().document().existingAXObjectCache())
255 cache->childrenChanged(&m_popupClient->ownerElement());
257 ASSERT(frame->localDOMWindow());
258 DOMWindowPagePopup::install(*frame->localDOMWindow(), *this, m_popupClient);
259 ASSERT(m_popupClient->ownerElement().document().existingAXObjectCache() == frame->document()->existingAXObjectCache());
261 RefPtr<SharedBuffer> data = SharedBuffer::create();
262 m_popupClient->writeDocument(data.get());
263 frame->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
265 return true;
268 void WebPagePopupImpl::postMessage(const String& message)
270 if (!m_page)
271 return;
272 ScriptForbiddenScope::AllowUserAgentScript allowScript;
273 if (LocalDOMWindow* window = toLocalFrame(m_page->mainFrame())->localDOMWindow())
274 window->dispatchEvent(MessageEvent::create(message));
277 void WebPagePopupImpl::destroyPage()
279 if (!m_page)
280 return;
282 m_page->willBeDestroyed();
283 m_page.clear();
286 AXObject* WebPagePopupImpl::rootAXObject()
288 if (!m_page || !m_page->mainFrame())
289 return 0;
290 Document* document = toLocalFrame(m_page->mainFrame())->document();
291 if (!document)
292 return 0;
293 AXObjectCache* cache = document->axObjectCache();
294 ASSERT(cache);
295 return toAXObjectCacheImpl(cache)->getOrCreate(document->layoutView());
298 void WebPagePopupImpl::setWindowRect(const IntRect& rect)
300 m_chromeClient->setWindowRect(rect);
303 void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer)
305 m_rootGraphicsLayer = layer;
306 m_rootLayer = layer ? layer->platformLayer() : 0;
308 setIsAcceleratedCompositingActive(layer);
309 if (m_layerTreeView) {
310 if (m_rootLayer) {
311 m_layerTreeView->setRootLayer(*m_rootLayer);
312 } else {
313 m_layerTreeView->clearRootLayer();
318 void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter)
320 if (m_isAcceleratedCompositingActive == enter)
321 return;
323 if (!enter) {
324 m_isAcceleratedCompositingActive = false;
325 } else if (m_layerTreeView) {
326 m_isAcceleratedCompositingActive = true;
327 } else {
328 TRACE_EVENT0("blink", "WebPagePopupImpl::setIsAcceleratedCompositingActive(true)");
330 m_widgetClient->initializeLayerTreeView();
331 m_layerTreeView = m_widgetClient->layerTreeView();
332 if (m_layerTreeView) {
333 m_layerTreeView->setVisible(true);
334 m_isAcceleratedCompositingActive = true;
335 m_layerTreeView->setDeviceScaleFactor(m_widgetClient->deviceScaleFactor());
336 } else {
337 m_isAcceleratedCompositingActive = false;
342 WebSize WebPagePopupImpl::size()
344 return m_popupClient->contentSize();
347 void WebPagePopupImpl::beginFrame(const WebBeginFrameArgs& frameTime)
349 if (!m_page)
350 return;
351 // FIXME: This should use frameTime.lastFrameTimeMonotonic but doing so
352 // breaks tests.
353 PageWidgetDelegate::animate(*m_page, monotonicallyIncreasingTime(), *m_page->deprecatedLocalMainFrame());
356 void WebPagePopupImpl::willCloseLayerTreeView()
358 setIsAcceleratedCompositingActive(false);
359 m_layerTreeView = 0;
362 void WebPagePopupImpl::layout()
364 if (!m_page)
365 return;
366 PageWidgetDelegate::layout(*m_page, *m_page->deprecatedLocalMainFrame());
369 void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect)
371 if (!m_closing)
372 PageWidgetDelegate::paint(*m_page, canvas, rect, *m_page->deprecatedLocalMainFrame());
375 void WebPagePopupImpl::resize(const WebSize& newSize)
377 m_windowRectInScreen = WebRect(m_windowRectInScreen.x, m_windowRectInScreen.y, newSize.width, newSize.height);
378 m_widgetClient->setWindowRect(m_windowRectInScreen);
380 if (m_page) {
381 toLocalFrame(m_page->mainFrame())->view()->resize(newSize);
382 m_page->frameHost().visualViewport().setSize(newSize);
385 m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
388 bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent& event)
390 return handleKeyEvent(PlatformKeyboardEventBuilder(event));
393 bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent& event)
395 return handleKeyEvent(PlatformKeyboardEventBuilder(event));
398 bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
400 if (m_closing || !m_page || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
401 return false;
402 if (event.type == WebInputEvent::GestureTap && !isGestureEventInWindow(event)) {
403 cancel();
404 return false;
406 LocalFrame& frame = *toLocalFrame(m_page->mainFrame());
407 return frame.eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
410 void WebPagePopupImpl::handleMouseDown(LocalFrame& mainFrame, const WebMouseEvent& event)
412 if (isMouseEventInWindow(event))
413 PageWidgetEventHandler::handleMouseDown(mainFrame, event);
414 else
415 cancel();
418 bool WebPagePopupImpl::handleMouseWheel(LocalFrame& mainFrame, const WebMouseWheelEvent& event)
420 if (isMouseEventInWindow(event))
421 return PageWidgetEventHandler::handleMouseWheel(mainFrame, event);
422 cancel();
423 return false;
426 bool WebPagePopupImpl::isMouseEventInWindow(const WebMouseEvent& event)
428 return IntRect(0, 0, m_windowRectInScreen.width, m_windowRectInScreen.height).contains(IntPoint(event.x, event.y));
431 bool WebPagePopupImpl::isGestureEventInWindow(const WebGestureEvent& event)
433 return IntRect(0, 0, m_windowRectInScreen.width, m_windowRectInScreen.height).contains(IntPoint(event.x, event.y));
436 bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
438 if (m_closing)
439 return false;
440 return PageWidgetDelegate::handleInputEvent(*this, event, m_page->deprecatedLocalMainFrame());
443 bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
445 if (m_closing || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
446 return false;
447 return toLocalFrame(m_page->mainFrame())->eventHandler().keyEvent(event);
450 void WebPagePopupImpl::setFocus(bool enable)
452 if (!m_page)
453 return;
454 m_page->focusController().setFocused(enable);
455 if (enable)
456 m_page->focusController().setActive(true);
459 void WebPagePopupImpl::close()
461 m_closing = true;
462 destroyPage(); // In case closePopup() was not called.
463 m_widgetClient = 0;
464 deref();
467 void WebPagePopupImpl::closePopup()
469 // This function can be called in EventDispatchForbiddenScope for the main
470 // document, and the following operations dispatch some events. It's safe
471 // because web authors can't listen the events.
472 EventDispatchForbiddenScope::AllowUserAgentEvents allowEvents;
474 if (m_page) {
475 toLocalFrame(m_page->mainFrame())->loader().stopAllLoaders();
476 ASSERT(m_page->deprecatedLocalMainFrame()->localDOMWindow());
477 DOMWindowPagePopup::uninstall(*m_page->deprecatedLocalMainFrame()->localDOMWindow());
479 m_closing = true;
481 destroyPage();
483 // m_widgetClient might be 0 because this widget might be already closed.
484 if (m_widgetClient) {
485 // closeWidgetSoon() will call this->close() later.
486 m_widgetClient->closeWidgetSoon();
489 m_popupClient->didClosePopup();
492 LocalDOMWindow* WebPagePopupImpl::window()
494 return m_page->deprecatedLocalMainFrame()->localDOMWindow();
497 void WebPagePopupImpl::layoutAndPaintAsync(WebLayoutAndPaintAsyncCallback* callback)
499 m_layerTreeView->layoutAndPaintAsync(callback);
502 void WebPagePopupImpl::compositeAndReadbackAsync(WebCompositeAndReadbackAsyncCallback* callback)
504 ASSERT(isAcceleratedCompositingActive());
505 m_layerTreeView->compositeAndReadbackAsync(callback);
508 WebPoint WebPagePopupImpl::positionRelativeToOwner()
510 WebRect windowRect = m_webView->client()->rootWindowRect();
511 return WebPoint(m_windowRectInScreen.x - windowRect.x, m_windowRectInScreen.y - windowRect.y);
514 void WebPagePopupImpl::cancel()
516 if (m_popupClient)
517 m_popupClient->closePopup();
520 // WebPagePopup ----------------------------------------------------------------
522 WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
524 if (!client)
525 CRASH();
526 // A WebPagePopupImpl instance usually has two references.
527 // - One owned by the instance itself. It represents the visible widget.
528 // - One owned by a WebViewImpl. It's released when the WebViewImpl ask the
529 // WebPagePopupImpl to close.
530 // We need them because the closing operation is asynchronous and the widget
531 // can be closed while the WebViewImpl is unaware of it.
532 return adoptRef(new WebPagePopupImpl(client)).leakRef();
535 } // namespace blink