Home | History | Annotate | Download | only in testing
      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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/testing/MockPagePopupDriver.h"
     28 
     29 #include "bindings/v8/ExceptionStatePlaceholder.h"
     30 #include "core/CSSPropertyNames.h"
     31 #include "core/CSSValueKeywords.h"
     32 #include "core/frame/LocalFrame.h"
     33 #include "core/html/HTMLIFrameElement.h"
     34 #include "core/loader/FrameLoadRequest.h"
     35 #include "core/loader/FrameLoader.h"
     36 #include "core/page/PagePopup.h"
     37 #include "core/page/PagePopupController.h"
     38 #include "platform/Timer.h"
     39 
     40 namespace WebCore {
     41 
     42 class MockPagePopup : public PagePopup, public RefCounted<MockPagePopup> {
     43 public:
     44     static PassRefPtr<MockPagePopup> create(PagePopupClient*, const IntRect& originBoundsInRootView, LocalFrame*);
     45     virtual ~MockPagePopup();
     46     bool initialize();
     47     void closeLater();
     48 
     49 private:
     50     MockPagePopup(PagePopupClient*, const IntRect& originBoundsInRootView, LocalFrame*);
     51     void close(Timer<MockPagePopup>*);
     52 
     53     PagePopupClient* m_popupClient;
     54     RefPtrWillBePersistent<HTMLIFrameElement> m_iframe;
     55     Timer<MockPagePopup> m_closeTimer;
     56 };
     57 
     58 inline MockPagePopup::MockPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView, LocalFrame* mainFrame)
     59     : m_popupClient(client)
     60     , m_closeTimer(this, &MockPagePopup::close)
     61 {
     62     Document* document = mainFrame->document();
     63     ASSERT(document);
     64     m_iframe = HTMLIFrameElement::create(*document);
     65     m_iframe->setIdAttribute("mock-page-popup");
     66     m_iframe->setInlineStyleProperty(CSSPropertyBorderWidth, 0.0, CSSPrimitiveValue::CSS_PX);
     67     m_iframe->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute);
     68     m_iframe->setInlineStyleProperty(CSSPropertyLeft, originBoundsInRootView.x(), CSSPrimitiveValue::CSS_PX, true);
     69     m_iframe->setInlineStyleProperty(CSSPropertyTop, originBoundsInRootView.maxY(), CSSPrimitiveValue::CSS_PX, true);
     70     if (document->body())
     71         document->body()->appendChild(m_iframe.get());
     72 }
     73 
     74 bool MockPagePopup::initialize()
     75 {
     76     const char scriptToSetUpPagePopupController[] = "<script>window.pagePopupController = parent.internals.pagePopupController;</script>";
     77     RefPtr<SharedBuffer> data = SharedBuffer::create(scriptToSetUpPagePopupController, sizeof(scriptToSetUpPagePopupController));
     78     m_popupClient->writeDocument(data.get());
     79     LocalFrame* localFrame = toLocalFrame(m_iframe->contentFrame());
     80     if (!localFrame)
     81         return false;
     82     localFrame->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
     83     return true;
     84 }
     85 
     86 PassRefPtr<MockPagePopup> MockPagePopup::create(PagePopupClient* client, const IntRect& originBoundsInRootView, LocalFrame* mainFrame)
     87 {
     88     return adoptRef(new MockPagePopup(client, originBoundsInRootView, mainFrame));
     89 }
     90 
     91 void MockPagePopup::closeLater()
     92 {
     93     ref();
     94     m_popupClient->didClosePopup();
     95     m_popupClient = 0;
     96     // This can be called in detach(), and we should not change DOM structure
     97     // during detach().
     98     m_closeTimer.startOneShot(0, FROM_HERE);
     99 }
    100 
    101 void MockPagePopup::close(Timer<MockPagePopup>*)
    102 {
    103     deref();
    104 }
    105 
    106 MockPagePopup::~MockPagePopup()
    107 {
    108     if (m_iframe && m_iframe->parentNode())
    109         m_iframe->parentNode()->removeChild(m_iframe.get());
    110 }
    111 
    112 inline MockPagePopupDriver::MockPagePopupDriver(LocalFrame* mainFrame)
    113     : m_mainFrame(mainFrame)
    114 {
    115 }
    116 
    117 PassOwnPtr<MockPagePopupDriver> MockPagePopupDriver::create(LocalFrame* mainFrame)
    118 {
    119     return adoptPtr(new MockPagePopupDriver(mainFrame));
    120 }
    121 
    122 MockPagePopupDriver::~MockPagePopupDriver()
    123 {
    124     closePagePopup(m_mockPagePopup.get());
    125 }
    126 
    127 PagePopup* MockPagePopupDriver::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
    128 {
    129     if (m_mockPagePopup)
    130         closePagePopup(m_mockPagePopup.get());
    131     if (!client || !m_mainFrame)
    132         return 0;
    133     m_pagePopupController = PagePopupController::create(client);
    134     m_mockPagePopup = MockPagePopup::create(client, originBoundsInRootView, m_mainFrame);
    135     if (!m_mockPagePopup->initialize()) {
    136         m_mockPagePopup->closeLater();
    137         m_mockPagePopup.clear();
    138     }
    139     return m_mockPagePopup.get();
    140 }
    141 
    142 void MockPagePopupDriver::closePagePopup(PagePopup* popup)
    143 {
    144     if (!popup || popup != m_mockPagePopup.get())
    145         return;
    146     m_mockPagePopup->closeLater();
    147     m_mockPagePopup.clear();
    148     m_pagePopupController->clearPagePopupClient();
    149     m_pagePopupController.clear();
    150 }
    151 
    152 }
    153