• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/TraceEvent.h"
47 #include "public/platform/WebCursorInfo.h"
48 #include "public/web/WebViewClient.h"
49 #include "public/web/WebWidgetClient.h"
50 #include "web/WebInputEventConversion.h"
51 #include "web/WebSettingsImpl.h"
52 #include "web/WebViewImpl.h"
53 
54 using namespace WebCore;
55 
56 namespace blink {
57 
58 class PagePopupChromeClient : public EmptyChromeClient {
59     WTF_MAKE_NONCOPYABLE(PagePopupChromeClient);
60     WTF_MAKE_FAST_ALLOCATED;
61 
62 public:
PagePopupChromeClient(WebPagePopupImpl * popup)63     explicit PagePopupChromeClient(WebPagePopupImpl* popup)
64         : m_popup(popup)
65     {
66         ASSERT(m_popup->widgetClient());
67     }
68 
69 private:
closeWindowSoon()70     virtual void closeWindowSoon() OVERRIDE
71     {
72         m_popup->closePopup();
73     }
74 
windowRect()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 
setWindowRect(const FloatRect & rect)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 
addMessageToConsole(LocalFrame *,MessageSource,MessageLevel,const String & message,unsigned lineNumber,const String &,const String &)86     virtual void addMessageToConsole(LocalFrame*, 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 
invalidateContentsAndRootView(const IntRect & paintRect)93     virtual void invalidateContentsAndRootView(const IntRect& paintRect) OVERRIDE
94     {
95         if (paintRect.isEmpty())
96             return;
97         m_popup->widgetClient()->didInvalidateRect(paintRect);
98     }
99 
scroll(const IntSize & scrollDelta,const IntRect & scrollRect,const IntRect & clipRect)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 
invalidateContentsForSlowScroll(const IntRect & updateRect)105     virtual void invalidateContentsForSlowScroll(const IntRect& updateRect) OVERRIDE
106     {
107         invalidateContentsAndRootView(updateRect);
108     }
109 
scheduleAnimation()110     virtual void scheduleAnimation() OVERRIDE
111     {
112         if (m_popup->isAcceleratedCompositingActive()) {
113             ASSERT(m_popup->m_layerTreeView);
114             m_popup->m_layerTreeView->setNeedsAnimate();
115             return;
116         }
117         m_popup->widgetClient()->scheduleAnimation();
118     }
119 
screenInfo() const120     virtual WebScreenInfo screenInfo() const OVERRIDE
121     {
122         return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
123     }
124 
webView() const125     virtual void* webView() const OVERRIDE
126     {
127         return m_popup->m_webView;
128     }
129 
minimumWindowSize() const130     virtual FloatSize minimumWindowSize() const OVERRIDE
131     {
132         return FloatSize(0, 0);
133     }
134 
setCursor(const WebCore::Cursor & cursor)135     virtual void setCursor(const WebCore::Cursor& cursor) OVERRIDE
136     {
137         if (m_popup->m_webView->client())
138             m_popup->m_webView->client()->didChangeCursor(WebCursorInfo(cursor));
139     }
140 
needTouchEvents(bool needsTouchEvents)141     virtual void needTouchEvents(bool needsTouchEvents) OVERRIDE
142     {
143         m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
144     }
145 
graphicsLayerFactory() const146     virtual GraphicsLayerFactory* graphicsLayerFactory() const OVERRIDE
147     {
148         return m_popup->m_webView->graphicsLayerFactory();
149     }
150 
attachRootGraphicsLayer(GraphicsLayer * graphicsLayer)151     virtual void attachRootGraphicsLayer(GraphicsLayer* graphicsLayer) OVERRIDE
152     {
153         m_popup->setRootGraphicsLayer(graphicsLayer);
154     }
155 
156     WebPagePopupImpl* m_popup;
157 };
158 
159 class PagePopupFeaturesClient : public ContextFeaturesClient {
160     virtual bool isEnabled(Document*, ContextFeatures::FeatureType, bool) OVERRIDE;
161 };
162 
isEnabled(Document *,ContextFeatures::FeatureType type,bool defaultValue)163 bool PagePopupFeaturesClient::isEnabled(Document*, ContextFeatures::FeatureType type, bool defaultValue)
164 {
165     if (type == ContextFeatures::PagePopup)
166         return true;
167     return defaultValue;
168 }
169 
170 // WebPagePopupImpl ----------------------------------------------------------------
171 
WebPagePopupImpl(WebWidgetClient * client)172 WebPagePopupImpl::WebPagePopupImpl(WebWidgetClient* client)
173     : m_widgetClient(client)
174     , m_closing(false)
175     , m_layerTreeView(0)
176     , m_rootLayer(0)
177     , m_rootGraphicsLayer(0)
178     , m_isAcceleratedCompositingActive(false)
179 {
180     ASSERT(client);
181 }
182 
~WebPagePopupImpl()183 WebPagePopupImpl::~WebPagePopupImpl()
184 {
185     ASSERT(!m_page);
186 }
187 
initialize(WebViewImpl * webView,PagePopupClient * popupClient,const IntRect &)188 bool WebPagePopupImpl::initialize(WebViewImpl* webView, PagePopupClient* popupClient, const IntRect&)
189 {
190     ASSERT(webView);
191     ASSERT(popupClient);
192     m_webView = webView;
193     m_popupClient = popupClient;
194 
195     resize(m_popupClient->contentSize());
196 
197     if (!initializePage())
198         return false;
199     m_widgetClient->show(WebNavigationPolicy());
200     setFocus(true);
201 
202     return true;
203 }
204 
initializePage()205 bool WebPagePopupImpl::initializePage()
206 {
207     Page::PageClients pageClients;
208     fillWithEmptyClients(pageClients);
209     m_chromeClient = adoptPtr(new PagePopupChromeClient(this));
210     pageClients.chromeClient = m_chromeClient.get();
211 
212     m_page = adoptPtrWillBeNoop(new Page(pageClients));
213     m_page->settings().setScriptEnabled(true);
214     m_page->settings().setAllowScriptsToCloseWindows(true);
215     m_page->setDeviceScaleFactor(m_webView->deviceScaleFactor());
216     m_page->settings().setDeviceSupportsTouch(m_webView->page()->settings().deviceSupportsTouch());
217 
218     provideContextFeaturesTo(*m_page, adoptPtr(new PagePopupFeaturesClient()));
219     static FrameLoaderClient* emptyFrameLoaderClient =  new EmptyFrameLoaderClient();
220     RefPtr<LocalFrame> frame = LocalFrame::create(emptyFrameLoaderClient, &m_page->frameHost(), 0);
221     frame->setView(FrameView::create(frame.get()));
222     frame->init();
223     frame->view()->resize(m_popupClient->contentSize());
224     frame->view()->setTransparent(false);
225 
226     ASSERT(frame->domWindow());
227     DOMWindowPagePopup::install(*frame->domWindow(), m_popupClient);
228 
229     RefPtr<SharedBuffer> data = SharedBuffer::create();
230     m_popupClient->writeDocument(data.get());
231     frame->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
232     return true;
233 }
234 
destroyPage()235 void WebPagePopupImpl::destroyPage()
236 {
237     if (!m_page)
238         return;
239 
240     m_page->willBeDestroyed();
241     m_page.clear();
242 }
243 
setRootGraphicsLayer(GraphicsLayer * layer)244 void WebPagePopupImpl::setRootGraphicsLayer(GraphicsLayer* layer)
245 {
246     m_rootGraphicsLayer = layer;
247     m_rootLayer = layer ? layer->platformLayer() : 0;
248 
249     setIsAcceleratedCompositingActive(layer);
250     if (m_layerTreeView) {
251         if (m_rootLayer) {
252             m_layerTreeView->setRootLayer(*m_rootLayer);
253         } else {
254             m_layerTreeView->clearRootLayer();
255         }
256     }
257 }
258 
setIsAcceleratedCompositingActive(bool enter)259 void WebPagePopupImpl::setIsAcceleratedCompositingActive(bool enter)
260 {
261     if (m_isAcceleratedCompositingActive == enter)
262         return;
263 
264     if (!enter) {
265         m_isAcceleratedCompositingActive = false;
266     } else if (m_layerTreeView) {
267         m_isAcceleratedCompositingActive = true;
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_isAcceleratedCompositingActive = true;
276             m_layerTreeView->setDeviceScaleFactor(m_widgetClient->deviceScaleFactor());
277         } else {
278             m_isAcceleratedCompositingActive = false;
279         }
280     }
281 }
282 
size()283 WebSize WebPagePopupImpl::size()
284 {
285     return m_popupClient->contentSize();
286 }
287 
animate(double)288 void WebPagePopupImpl::animate(double)
289 {
290     PageWidgetDelegate::animate(m_page.get(), monotonicallyIncreasingTime());
291 }
292 
willCloseLayerTreeView()293 void WebPagePopupImpl::willCloseLayerTreeView()
294 {
295     setIsAcceleratedCompositingActive(false);
296     m_layerTreeView = 0;
297 }
298 
layout()299 void WebPagePopupImpl::layout()
300 {
301     PageWidgetDelegate::layout(m_page.get());
302 }
303 
paint(WebCanvas * canvas,const WebRect & rect)304 void WebPagePopupImpl::paint(WebCanvas* canvas, const WebRect& rect)
305 {
306     if (!m_closing)
307         PageWidgetDelegate::paint(m_page.get(), 0, canvas, rect, PageWidgetDelegate::Opaque);
308 }
309 
resize(const WebSize & newSize)310 void WebPagePopupImpl::resize(const WebSize& newSize)
311 {
312     m_windowRectInScreen = WebRect(m_windowRectInScreen.x, m_windowRectInScreen.y, newSize.width, newSize.height);
313     m_widgetClient->setWindowRect(m_windowRectInScreen);
314 
315     if (m_page)
316         toLocalFrame(m_page->mainFrame())->view()->resize(newSize);
317     m_widgetClient->didInvalidateRect(WebRect(0, 0, newSize.width, newSize.height));
318 }
319 
handleKeyEvent(const WebKeyboardEvent &)320 bool WebPagePopupImpl::handleKeyEvent(const WebKeyboardEvent&)
321 {
322     // The main WebView receives key events and forward them to this via handleKeyEvent().
323     ASSERT_NOT_REACHED();
324     return false;
325 }
326 
handleCharEvent(const WebKeyboardEvent &)327 bool WebPagePopupImpl::handleCharEvent(const WebKeyboardEvent&)
328 {
329     // The main WebView receives key events and forward them to this via handleKeyEvent().
330     ASSERT_NOT_REACHED();
331     return false;
332 }
333 
handleGestureEvent(const WebGestureEvent & event)334 bool WebPagePopupImpl::handleGestureEvent(const WebGestureEvent& event)
335 {
336     if (m_closing || !m_page || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
337         return false;
338     LocalFrame& frame = *toLocalFrame(m_page->mainFrame());
339     return frame.eventHandler().handleGestureEvent(PlatformGestureEventBuilder(frame.view(), event));
340 }
341 
handleInputEvent(const WebInputEvent & event)342 bool WebPagePopupImpl::handleInputEvent(const WebInputEvent& event)
343 {
344     if (m_closing)
345         return false;
346     return PageWidgetDelegate::handleInputEvent(m_page.get(), *this, event);
347 }
348 
handleKeyEvent(const PlatformKeyboardEvent & event)349 bool WebPagePopupImpl::handleKeyEvent(const PlatformKeyboardEvent& event)
350 {
351     if (m_closing || !m_page->mainFrame() || !toLocalFrame(m_page->mainFrame())->view())
352         return false;
353     return toLocalFrame(m_page->mainFrame())->eventHandler().keyEvent(event);
354 }
355 
setFocus(bool enable)356 void WebPagePopupImpl::setFocus(bool enable)
357 {
358     if (!m_page)
359         return;
360     m_page->focusController().setFocused(enable);
361     if (enable)
362         m_page->focusController().setActive(true);
363 }
364 
close()365 void WebPagePopupImpl::close()
366 {
367     m_closing = true;
368     destroyPage(); // In case closePopup() was not called.
369     m_widgetClient = 0;
370     deref();
371 }
372 
closePopup()373 void WebPagePopupImpl::closePopup()
374 {
375     if (m_page) {
376         toLocalFrame(m_page->mainFrame())->loader().stopAllLoaders();
377         ASSERT(m_page->mainFrame()->domWindow());
378         DOMWindowPagePopup::uninstall(*m_page->mainFrame()->domWindow());
379     }
380     m_closing = true;
381 
382     destroyPage();
383 
384     // m_widgetClient might be 0 because this widget might be already closed.
385     if (m_widgetClient) {
386         // closeWidgetSoon() will call this->close() later.
387         m_widgetClient->closeWidgetSoon();
388     }
389 
390     m_popupClient->didClosePopup();
391 }
392 
393 // WebPagePopup ----------------------------------------------------------------
394 
create(WebWidgetClient * client)395 WebPagePopup* WebPagePopup::create(WebWidgetClient* client)
396 {
397     if (!client)
398         CRASH();
399     // A WebPagePopupImpl instance usually has two references.
400     //  - One owned by the instance itself. It represents the visible widget.
401     //  - One owned by a WebViewImpl. It's released when the WebViewImpl ask the
402     //    WebPagePopupImpl to close.
403     // We need them because the closing operation is asynchronous and the widget
404     // can be closed while the WebViewImpl is unaware of it.
405     return adoptRef(new WebPagePopupImpl(client)).leakRef();
406 }
407 
408 } // namespace blink
409