Home | History | Annotate | Download | only in web
      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:
     63     explicit PagePopupChromeClient(WebPagePopupImpl* popup)
     64         : m_popup(popup)
     65     {
     66         ASSERT(m_popup->widgetClient());
     67     }
     68 
     69 private:
     70     virtual void closeWindowSoon() OVERRIDE
     71     {
     72         m_popup->closePopup();
     73     }
     74 
     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 
     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 
     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 
     93     virtual void invalidateContentsAndRootView(const IntRect& paintRect) OVERRIDE
     94     {
     95         if (paintRect.isEmpty())
     96             return;
     97         m_popup->widgetClient()->didInvalidateRect(paintRect);
     98     }
     99 
    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 
    105     virtual void invalidateContentsForSlowScroll(const IntRect& updateRect) OVERRIDE
    106     {
    107         invalidateContentsAndRootView(updateRect);
    108     }
    109 
    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 
    120     virtual WebScreenInfo screenInfo() const OVERRIDE
    121     {
    122         return m_popup->m_webView->client() ? m_popup->m_webView->client()->screenInfo() : WebScreenInfo();
    123     }
    124 
    125     virtual void* webView() const OVERRIDE
    126     {
    127         return m_popup->m_webView;
    128     }
    129 
    130     virtual FloatSize minimumWindowSize() const OVERRIDE
    131     {
    132         return FloatSize(0, 0);
    133     }
    134 
    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 
    141     virtual void needTouchEvents(bool needsTouchEvents) OVERRIDE
    142     {
    143         m_popup->widgetClient()->hasTouchEventHandlers(needsTouchEvents);
    144     }
    145 
    146     virtual GraphicsLayerFactory* graphicsLayerFactory() const OVERRIDE
    147     {
    148         return m_popup->m_webView->graphicsLayerFactory();
    149     }
    150 
    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 
    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 
    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 
    183 WebPagePopupImpl::~WebPagePopupImpl()
    184 {
    185     ASSERT(!m_page);
    186 }
    187 
    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 
    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 
    235 void WebPagePopupImpl::destroyPage()
    236 {
    237     if (!m_page)
    238         return;
    239 
    240     m_page->willBeDestroyed();
    241     m_page.clear();
    242 }
    243 
    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 
    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 
    283 WebSize WebPagePopupImpl::size()
    284 {
    285     return m_popupClient->contentSize();
    286 }
    287 
    288 void WebPagePopupImpl::animate(double)
    289 {
    290     PageWidgetDelegate::animate(m_page.get(), monotonicallyIncreasingTime());
    291 }
    292 
    293 void WebPagePopupImpl::willCloseLayerTreeView()
    294 {
    295     setIsAcceleratedCompositingActive(false);
    296     m_layerTreeView = 0;
    297 }
    298 
    299 void WebPagePopupImpl::layout()
    300 {
    301     PageWidgetDelegate::layout(m_page.get());
    302 }
    303 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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