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/core/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 blink {
     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     virtual AXObject* rootAXObject() OVERRIDE { return 0; }
     53 
     54     PagePopupClient* m_popupClient;
     55     RefPtrWillBePersistent<HTMLIFrameElement> m_iframe;
     56     Timer<MockPagePopup> m_closeTimer;
     57 };
     58 
     59 inline MockPagePopup::MockPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView, LocalFrame* mainFrame)
     60     : m_popupClient(client)
     61     , m_closeTimer(this, &MockPagePopup::close)
     62 {
     63     Document* document = mainFrame->document();
     64     ASSERT(document);
     65     m_iframe = HTMLIFrameElement::create(*document);
     66     m_iframe->setIdAttribute("mock-page-popup");
     67     m_iframe->setInlineStyleProperty(CSSPropertyBorderWidth, 0.0, CSSPrimitiveValue::CSS_PX);
     68     m_iframe->setInlineStyleProperty(CSSPropertyPosition, CSSValueAbsolute);
     69     m_iframe->setInlineStyleProperty(CSSPropertyLeft, originBoundsInRootView.x(), CSSPrimitiveValue::CSS_PX, true);
     70     m_iframe->setInlineStyleProperty(CSSPropertyTop, originBoundsInRootView.maxY(), CSSPrimitiveValue::CSS_PX, true);
     71     if (document->body())
     72         document->body()->appendChild(m_iframe.get());
     73 }
     74 
     75 bool MockPagePopup::initialize()
     76 {
     77     const char scriptToSetUpPagePopupController[] = "<script>window.pagePopupController = parent.internals.pagePopupController;</script>";
     78     RefPtr<SharedBuffer> data = SharedBuffer::create(scriptToSetUpPagePopupController, sizeof(scriptToSetUpPagePopupController));
     79     m_popupClient->writeDocument(data.get());
     80     LocalFrame* localFrame = toLocalFrame(m_iframe->contentFrame());
     81     if (!localFrame)
     82         return false;
     83     localFrame->loader().load(FrameLoadRequest(0, blankURL(), SubstituteData(data, "text/html", "UTF-8", KURL(), ForceSynchronousLoad)));
     84     return true;
     85 }
     86 
     87 PassRefPtr<MockPagePopup> MockPagePopup::create(PagePopupClient* client, const IntRect& originBoundsInRootView, LocalFrame* mainFrame)
     88 {
     89     return adoptRef(new MockPagePopup(client, originBoundsInRootView, mainFrame));
     90 }
     91 
     92 void MockPagePopup::closeLater()
     93 {
     94     ref();
     95     m_popupClient->didClosePopup();
     96     m_popupClient = 0;
     97     // This can be called in detach(), and we should not change DOM structure
     98     // during detach().
     99     m_closeTimer.startOneShot(0, FROM_HERE);
    100 }
    101 
    102 void MockPagePopup::close(Timer<MockPagePopup>*)
    103 {
    104     deref();
    105 }
    106 
    107 MockPagePopup::~MockPagePopup()
    108 {
    109     if (m_iframe && m_iframe->parentNode())
    110         m_iframe->parentNode()->removeChild(m_iframe.get());
    111 }
    112 
    113 inline MockPagePopupDriver::MockPagePopupDriver(LocalFrame* mainFrame)
    114     : m_mainFrame(mainFrame)
    115 {
    116 }
    117 
    118 PassOwnPtr<MockPagePopupDriver> MockPagePopupDriver::create(LocalFrame* mainFrame)
    119 {
    120     return adoptPtr(new MockPagePopupDriver(mainFrame));
    121 }
    122 
    123 MockPagePopupDriver::~MockPagePopupDriver()
    124 {
    125     closePagePopup(m_mockPagePopup.get());
    126 }
    127 
    128 PagePopup* MockPagePopupDriver::openPagePopup(PagePopupClient* client, const IntRect& originBoundsInRootView)
    129 {
    130     if (m_mockPagePopup)
    131         closePagePopup(m_mockPagePopup.get());
    132     if (!client || !m_mainFrame)
    133         return 0;
    134     m_pagePopupController = PagePopupController::create(client);
    135     m_mockPagePopup = MockPagePopup::create(client, originBoundsInRootView, m_mainFrame);
    136     if (!m_mockPagePopup->initialize()) {
    137         m_mockPagePopup->closeLater();
    138         m_mockPagePopup.clear();
    139     }
    140     return m_mockPagePopup.get();
    141 }
    142 
    143 void MockPagePopupDriver::closePagePopup(PagePopup* popup)
    144 {
    145     if (!popup || popup != m_mockPagePopup.get())
    146         return;
    147     m_mockPagePopup->closeLater();
    148     m_mockPagePopup.clear();
    149     m_pagePopupController->clearPagePopupClient();
    150     m_pagePopupController.clear();
    151 }
    152 
    153 }
    154