WebCore/html/HTMLFrameElementBase.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
       
     3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
       
     4  *           (C) 2000 Simon Hausmann (hausmann@kde.org)
       
     5  *           (C) 2001 Dirk Mueller (mueller@kde.org)
       
     6  * Copyright (C) 2004, 2006, 2008, 2009 Apple Inc. All rights reserved.
       
     7  *
       
     8  * This library is free software; you can redistribute it and/or
       
     9  * modify it under the terms of the GNU Library General Public
       
    10  * License as published by the Free Software Foundation; either
       
    11  * version 2 of the License, or (at your option) any later version.
       
    12  *
       
    13  * This library is distributed in the hope that it will be useful,
       
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    16  * Library General Public License for more details.
       
    17  *
       
    18  * You should have received a copy of the GNU Library General Public License
       
    19  * along with this library; see the file COPYING.LIB.  If not, write to
       
    20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    21  * Boston, MA 02110-1301, USA.
       
    22  */
       
    23 
       
    24 #include "config.h"
       
    25 #include "HTMLFrameElementBase.h"
       
    26 
       
    27 #include "Attribute.h"
       
    28 #include "CSSHelper.h"
       
    29 #include "Document.h"
       
    30 #include "EventNames.h"
       
    31 #include "FocusController.h"
       
    32 #include "Frame.h"
       
    33 #include "FrameLoader.h"
       
    34 #include "FrameTree.h"
       
    35 #include "FrameView.h"
       
    36 #include "HTMLFrameSetElement.h"
       
    37 #include "HTMLNames.h"
       
    38 #include "KURL.h"
       
    39 #include "Page.h"
       
    40 #include "RenderFrame.h"
       
    41 #include "ScriptController.h"
       
    42 #include "ScriptEventListener.h"
       
    43 #include "Settings.h"
       
    44 
       
    45 namespace WebCore {
       
    46 
       
    47 using namespace HTMLNames;
       
    48 
       
    49 HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document* document)
       
    50     : HTMLFrameOwnerElement(tagName, document)
       
    51     , m_scrolling(ScrollbarAuto)
       
    52     , m_marginWidth(-1)
       
    53     , m_marginHeight(-1)
       
    54     , m_checkAttachedTimer(this, &HTMLFrameElementBase::checkAttachedTimerFired)
       
    55     , m_viewSource(false)
       
    56     , m_shouldOpenURLAfterAttach(false)
       
    57     , m_remainsAliveOnRemovalFromTree(false)
       
    58 {
       
    59 }
       
    60 
       
    61 bool HTMLFrameElementBase::isURLAllowed() const
       
    62 {
       
    63     if (m_URL.isEmpty())
       
    64         return true;
       
    65 
       
    66     const KURL& completeURL = document()->completeURL(m_URL);
       
    67 
       
    68     if (protocolIsJavaScript(completeURL)) { 
       
    69         Document* contentDoc = this->contentDocument();
       
    70         if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame()))
       
    71             return false;
       
    72     }
       
    73 
       
    74     if (Frame* parentFrame = document()->frame()) {
       
    75         if (parentFrame->page()->frameCount() >= Page::maxNumberOfFrames)
       
    76             return false;
       
    77     }
       
    78 
       
    79     // We allow one level of self-reference because some sites depend on that.
       
    80     // But we don't allow more than one.
       
    81     bool foundSelfReference = false;
       
    82     for (Frame* frame = document()->frame(); frame; frame = frame->tree()->parent()) {
       
    83         if (equalIgnoringFragmentIdentifier(frame->loader()->url(), completeURL)) {
       
    84             if (foundSelfReference)
       
    85                 return false;
       
    86             foundSelfReference = true;
       
    87         }
       
    88     }
       
    89     
       
    90     return true;
       
    91 }
       
    92 
       
    93 void HTMLFrameElementBase::openURL(bool lockHistory, bool lockBackForwardList)
       
    94 {
       
    95     ASSERT(!m_frameName.isEmpty());
       
    96 
       
    97     if (!isURLAllowed())
       
    98         return;
       
    99 
       
   100     if (m_URL.isEmpty())
       
   101         m_URL = blankURL().string();
       
   102 
       
   103     Frame* parentFrame = document()->frame();
       
   104     if (!parentFrame)
       
   105         return;
       
   106 
       
   107     parentFrame->loader()->subframeLoader()->requestFrame(this, m_URL, m_frameName, lockHistory, lockBackForwardList);
       
   108     if (contentFrame())
       
   109         contentFrame()->setInViewSourceMode(viewSourceMode());
       
   110 }
       
   111 
       
   112 void HTMLFrameElementBase::parseMappedAttribute(Attribute* attr)
       
   113 {
       
   114     if (attr->name() == srcAttr)
       
   115         setLocation(deprecatedParseURL(attr->value()));
       
   116     else if (isIdAttributeName(attr->name())) {
       
   117         // Important to call through to base for the id attribute so the hasID bit gets set.
       
   118         HTMLFrameOwnerElement::parseMappedAttribute(attr);
       
   119         m_frameName = attr->value();
       
   120     } else if (attr->name() == nameAttr) {
       
   121         m_frameName = attr->value();
       
   122         // FIXME: If we are already attached, this doesn't actually change the frame's name.
       
   123         // FIXME: If we are already attached, this doesn't check for frame name
       
   124         // conflicts and generate a unique frame name.
       
   125     } else if (attr->name() == marginwidthAttr) {
       
   126         m_marginWidth = attr->value().toInt();
       
   127         // FIXME: If we are already attached, this has no effect.
       
   128     } else if (attr->name() == marginheightAttr) {
       
   129         m_marginHeight = attr->value().toInt();
       
   130         // FIXME: If we are already attached, this has no effect.
       
   131     } else if (attr->name() == scrollingAttr) {
       
   132         // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling."
       
   133         if (equalIgnoringCase(attr->value(), "auto") || equalIgnoringCase(attr->value(), "yes"))
       
   134             m_scrolling = document()->frameElementsShouldIgnoreScrolling() ? ScrollbarAlwaysOff : ScrollbarAuto;
       
   135         else if (equalIgnoringCase(attr->value(), "no"))
       
   136             m_scrolling = ScrollbarAlwaysOff;
       
   137         // FIXME: If we are already attached, this has no effect.
       
   138     } else if (attr->name() == viewsourceAttr) {
       
   139         m_viewSource = !attr->isNull();
       
   140         if (contentFrame())
       
   141             contentFrame()->setInViewSourceMode(viewSourceMode());
       
   142     } else if (attr->name() == onloadAttr)
       
   143         setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr));
       
   144     else if (attr->name() == onbeforeloadAttr)
       
   145         setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr));
       
   146     else if (attr->name() == onbeforeunloadAttr) {
       
   147         // FIXME: should <frame> elements have beforeunload handlers?
       
   148         setAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(this, attr));
       
   149     } else
       
   150         HTMLFrameOwnerElement::parseMappedAttribute(attr);
       
   151 }
       
   152 
       
   153 void HTMLFrameElementBase::setName()
       
   154 {
       
   155     m_frameName = getAttribute(nameAttr);
       
   156     if (m_frameName.isNull())
       
   157         m_frameName = getIdAttribute();
       
   158     
       
   159     if (Frame* parentFrame = document()->frame())
       
   160         m_frameName = parentFrame->tree()->uniqueChildName(m_frameName);
       
   161 }
       
   162 
       
   163 void HTMLFrameElementBase::setNameAndOpenURL()
       
   164 {
       
   165     setName();
       
   166     openURL();
       
   167 }
       
   168 
       
   169 void HTMLFrameElementBase::setNameAndOpenURLCallback(Node* n)
       
   170 {
       
   171     static_cast<HTMLFrameElementBase*>(n)->setNameAndOpenURL();
       
   172 }
       
   173 
       
   174 void HTMLFrameElementBase::updateOnReparenting()
       
   175 {
       
   176     ASSERT(m_remainsAliveOnRemovalFromTree);
       
   177 
       
   178     if (Frame* frame = contentFrame())
       
   179         frame->transferChildFrameToNewDocument();
       
   180 }
       
   181 
       
   182 void HTMLFrameElementBase::insertedIntoDocument()
       
   183 {
       
   184     HTMLFrameOwnerElement::insertedIntoDocument();
       
   185     
       
   186     // We delay frame loading until after the render tree is fully constructed.
       
   187     // Othewise, a synchronous load that executed JavaScript would see incorrect 
       
   188     // (0) values for the frame's renderer-dependent properties, like width.
       
   189     m_shouldOpenURLAfterAttach = true;
       
   190 
       
   191     if (m_remainsAliveOnRemovalFromTree)
       
   192         updateOnReparenting();
       
   193 }
       
   194 
       
   195 void HTMLFrameElementBase::removedFromDocument()
       
   196 {
       
   197     m_shouldOpenURLAfterAttach = false;
       
   198 
       
   199     HTMLFrameOwnerElement::removedFromDocument();
       
   200 }
       
   201 
       
   202 void HTMLFrameElementBase::attach()
       
   203 {
       
   204     if (m_shouldOpenURLAfterAttach) {
       
   205         m_shouldOpenURLAfterAttach = false;
       
   206         if (!m_remainsAliveOnRemovalFromTree)
       
   207             queuePostAttachCallback(&HTMLFrameElementBase::setNameAndOpenURLCallback, this);
       
   208     }
       
   209 
       
   210     setRemainsAliveOnRemovalFromTree(false);
       
   211 
       
   212     HTMLFrameOwnerElement::attach();
       
   213     
       
   214     if (RenderPart* renderPart = toRenderPart(renderer())) {
       
   215         if (Frame* frame = contentFrame())
       
   216             renderPart->setWidget(frame->view());
       
   217     }
       
   218 }
       
   219 
       
   220 KURL HTMLFrameElementBase::location() const
       
   221 {
       
   222     return document()->completeURL(getAttribute(srcAttr));
       
   223 }
       
   224 
       
   225 void HTMLFrameElementBase::setLocation(const String& str)
       
   226 {
       
   227     Settings* settings = document()->settings();
       
   228     if (settings && settings->needsAcrobatFrameReloadingQuirk() && m_URL == str)
       
   229         return;
       
   230 
       
   231     m_URL = AtomicString(str);
       
   232 
       
   233     if (inDocument())
       
   234         openURL(false, false);
       
   235 }
       
   236 
       
   237 bool HTMLFrameElementBase::supportsFocus() const
       
   238 {
       
   239     return true;
       
   240 }
       
   241 
       
   242 void HTMLFrameElementBase::setFocus(bool received)
       
   243 {
       
   244     HTMLFrameOwnerElement::setFocus(received);
       
   245     if (Page* page = document()->page()) {
       
   246         if (received)
       
   247             page->focusController()->setFocusedFrame(contentFrame());
       
   248         else if (page->focusController()->focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away.
       
   249             page->focusController()->setFocusedFrame(0);
       
   250     }
       
   251 }
       
   252 
       
   253 bool HTMLFrameElementBase::isURLAttribute(Attribute *attr) const
       
   254 {
       
   255     return attr->name() == srcAttr;
       
   256 }
       
   257 
       
   258 int HTMLFrameElementBase::width() const
       
   259 {
       
   260     if (!renderer())
       
   261         return 0;
       
   262     
       
   263     document()->updateLayoutIgnorePendingStylesheets();
       
   264     return toRenderBox(renderer())->width();
       
   265 }
       
   266 
       
   267 int HTMLFrameElementBase::height() const
       
   268 {
       
   269     if (!renderer())
       
   270         return 0;
       
   271     
       
   272     document()->updateLayoutIgnorePendingStylesheets();
       
   273     return toRenderBox(renderer())->height();
       
   274 }
       
   275 
       
   276 void HTMLFrameElementBase::setRemainsAliveOnRemovalFromTree(bool value)
       
   277 {
       
   278     m_remainsAliveOnRemovalFromTree = value;
       
   279 
       
   280     // There is a possibility that JS will do document.adoptNode() on this element but will not insert it into the tree.
       
   281     // Start the async timer that is normally stopped by attach(). If it's not stopped and fires, it'll unload the frame.
       
   282     if (value)
       
   283         m_checkAttachedTimer.startOneShot(0);
       
   284     else
       
   285         m_checkAttachedTimer.stop();
       
   286 }
       
   287 
       
   288 void HTMLFrameElementBase::checkAttachedTimerFired(Timer<HTMLFrameElementBase>*)
       
   289 {
       
   290     ASSERT(!attached());
       
   291     ASSERT(m_remainsAliveOnRemovalFromTree);
       
   292 
       
   293     m_remainsAliveOnRemovalFromTree = false;
       
   294     willRemove();
       
   295 }
       
   296 
       
   297 void HTMLFrameElementBase::willRemove()
       
   298 {
       
   299     if (m_remainsAliveOnRemovalFromTree)
       
   300         return;
       
   301 
       
   302     HTMLFrameOwnerElement::willRemove();
       
   303 }
       
   304 
       
   305 } // namespace WebCore