Home | History | Annotate | Download | only in web
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "config.h"
      6 #include "public/web/WebFrame.h"
      7 
      8 #include "core/frame/RemoteFrame.h"
      9 #include "core/html/HTMLFrameOwnerElement.h"
     10 #include "platform/UserGestureIndicator.h"
     11 #include "platform/heap/Handle.h"
     12 #include "web/OpenedFrameTracker.h"
     13 #include "web/WebLocalFrameImpl.h"
     14 #include "web/WebRemoteFrameImpl.h"
     15 #include <algorithm>
     16 
     17 namespace blink {
     18 
     19 Frame* toCoreFrame(const WebFrame* frame)
     20 {
     21     if (!frame)
     22         return 0;
     23 
     24     return frame->isWebLocalFrame()
     25         ? static_cast<Frame*>(toWebLocalFrameImpl(frame)->frame())
     26         : toWebRemoteFrameImpl(frame)->frame();
     27 }
     28 
     29 bool WebFrame::swap(WebFrame* frame)
     30 {
     31     using std::swap;
     32     RefPtrWillBeRawPtr<Frame> oldFrame = toCoreFrame(this);
     33 
     34     // All child frames must be detached first.
     35     oldFrame->detachChildren();
     36 
     37     // If the frame has been detached during detaching its children, return
     38     // immediately.
     39     // FIXME: There is no unit test for this condition, so one needs to be
     40     // written.
     41     if (!oldFrame->host())
     42         return false;
     43 
     44     // The frame being swapped in should not have a Frame associated
     45     // with it yet.
     46     ASSERT(!toCoreFrame(frame));
     47 
     48     if (m_parent) {
     49         if (m_parent->m_firstChild == this)
     50             m_parent->m_firstChild = frame;
     51         if (m_parent->m_lastChild == this)
     52             m_parent->m_lastChild = frame;
     53         swap(m_parent, frame->m_parent);
     54     }
     55 
     56     if (m_previousSibling) {
     57         m_previousSibling->m_nextSibling = frame;
     58         swap(m_previousSibling, frame->m_previousSibling);
     59     }
     60     if (m_nextSibling) {
     61         m_nextSibling->m_previousSibling = frame;
     62         swap(m_nextSibling, frame->m_nextSibling);
     63     }
     64 
     65     if (m_opener) {
     66         m_opener->m_openedFrameTracker->remove(this);
     67         m_opener->m_openedFrameTracker->add(frame);
     68         swap(m_opener, frame->m_opener);
     69     }
     70     if (!m_openedFrameTracker->isEmpty()) {
     71         m_openedFrameTracker->updateOpener(frame);
     72         frame->m_openedFrameTracker.reset(m_openedFrameTracker.release());
     73     }
     74 
     75     // Finally, clone the state of the current Frame into one matching
     76     // the type of the passed in WebFrame.
     77     // FIXME: This is a bit clunky; this results in pointless decrements and
     78     // increments of connected subframes.
     79     FrameOwner* owner = oldFrame->owner();
     80     oldFrame->disconnectOwnerElement();
     81     if (frame->isWebLocalFrame()) {
     82         toWebLocalFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name(), nullAtom);
     83     } else {
     84         toWebRemoteFrameImpl(frame)->initializeCoreFrame(oldFrame->host(), owner, oldFrame->tree().name());
     85     }
     86 
     87     return true;
     88 }
     89 
     90 void WebFrame::detach()
     91 {
     92     toCoreFrame(this)->detach();
     93 }
     94 
     95 WebFrame* WebFrame::opener() const
     96 {
     97     return m_opener;
     98 }
     99 
    100 void WebFrame::setOpener(WebFrame* opener)
    101 {
    102     if (m_opener)
    103         m_opener->m_openedFrameTracker->remove(this);
    104     if (opener)
    105         opener->m_openedFrameTracker->add(this);
    106     m_opener = opener;
    107 }
    108 
    109 void WebFrame::appendChild(WebFrame* child)
    110 {
    111     // FIXME: Original code asserts that the frames have the same Page. We
    112     // should add an equivalent check... figure out what.
    113     child->m_parent = this;
    114     WebFrame* oldLast = m_lastChild;
    115     m_lastChild = child;
    116 
    117     if (oldLast) {
    118         child->m_previousSibling = oldLast;
    119         oldLast->m_nextSibling = child;
    120     } else {
    121         m_firstChild = child;
    122     }
    123 
    124     toCoreFrame(this)->tree().invalidateScopedChildCount();
    125 }
    126 
    127 void WebFrame::removeChild(WebFrame* child)
    128 {
    129     child->m_parent = 0;
    130 
    131     if (m_firstChild == child)
    132         m_firstChild = child->m_nextSibling;
    133     else
    134         child->m_previousSibling->m_nextSibling = child->m_nextSibling;
    135 
    136     if (m_lastChild == child)
    137         m_lastChild = child->m_previousSibling;
    138     else
    139         child->m_nextSibling->m_previousSibling = child->m_previousSibling;
    140 
    141     child->m_previousSibling = child->m_nextSibling = 0;
    142 
    143     toCoreFrame(this)->tree().invalidateScopedChildCount();
    144 }
    145 
    146 WebFrame* WebFrame::parent() const
    147 {
    148     return m_parent;
    149 }
    150 
    151 WebFrame* WebFrame::top() const
    152 {
    153     WebFrame* frame = const_cast<WebFrame*>(this);
    154     for (WebFrame* parent = frame; parent; parent = parent->m_parent)
    155         frame = parent;
    156     return frame;
    157 }
    158 
    159 WebFrame* WebFrame::firstChild() const
    160 {
    161     return m_firstChild;
    162 }
    163 
    164 WebFrame* WebFrame::lastChild() const
    165 {
    166     return m_lastChild;
    167 }
    168 
    169 WebFrame* WebFrame::previousSibling() const
    170 {
    171     return m_previousSibling;
    172 }
    173 
    174 WebFrame* WebFrame::nextSibling() const
    175 {
    176     return m_nextSibling;
    177 }
    178 
    179 WebFrame* WebFrame::traversePrevious(bool wrap) const
    180 {
    181     if (Frame* frame = toCoreFrame(this))
    182         return fromFrame(frame->tree().traversePreviousWithWrap(wrap));
    183     return 0;
    184 }
    185 
    186 WebFrame* WebFrame::traverseNext(bool wrap) const
    187 {
    188     if (Frame* frame = toCoreFrame(this))
    189         return fromFrame(frame->tree().traverseNextWithWrap(wrap));
    190     return 0;
    191 }
    192 
    193 WebFrame* WebFrame::findChildByName(const WebString& name) const
    194 {
    195     Frame* frame = toCoreFrame(this);
    196     if (!frame)
    197         return 0;
    198     // FIXME: It's not clear this should ever be called to find a remote frame.
    199     // Perhaps just disallow that completely?
    200     return fromFrame(frame->tree().child(name));
    201 }
    202 
    203 WebFrame* WebFrame::fromFrame(Frame* frame)
    204 {
    205     if (!frame)
    206         return 0;
    207 
    208     if (frame->isLocalFrame())
    209         return WebLocalFrameImpl::fromFrame(toLocalFrame(*frame));
    210     return WebRemoteFrameImpl::fromFrame(toRemoteFrame(*frame));
    211 }
    212 
    213 WebFrame::WebFrame()
    214     : m_parent(0)
    215     , m_previousSibling(0)
    216     , m_nextSibling(0)
    217     , m_firstChild(0)
    218     , m_lastChild(0)
    219     , m_opener(0)
    220     , m_openedFrameTracker(new OpenedFrameTracker)
    221 {
    222 }
    223 
    224 WebFrame::~WebFrame()
    225 {
    226     m_openedFrameTracker.reset(0);
    227 }
    228 
    229 void WebFrame::traceChildren(Visitor* visitor, WebFrame* frame)
    230 {
    231 #if ENABLE(OILPAN)
    232     // Trace the children frames.
    233     WebFrame* child = frame ? frame->firstChild() : 0;
    234     while (child) {
    235         if (child->isWebLocalFrame())
    236             visitor->trace(toWebLocalFrameImpl(child));
    237         else
    238             visitor->trace(toWebRemoteFrameImpl(child));
    239 
    240         child = child->nextSibling();
    241     }
    242 #endif
    243 }
    244 
    245 } // namespace blink
    246