Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / web / WebFrame.cpp
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