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 "Document.h" 29#include "EventNames.h" 30#include "FocusController.h" 31#include "Frame.h" 32#include "FrameLoader.h" 33#include "FrameView.h" 34#include "HTMLNames.h" 35#include "HTMLParserIdioms.h" 36#include "KURL.h" 37#include "Page.h" 38#include "RenderPart.h" 39#include "ScriptController.h" 40#include "ScriptEventListener.h" 41#include "Settings.h" 42 43namespace WebCore { 44 45using namespace HTMLNames; 46 47HTMLFrameElementBase::HTMLFrameElementBase(const QualifiedName& tagName, Document* document) 48 : HTMLFrameOwnerElement(tagName, document) 49 , m_scrolling(ScrollbarAuto) 50 , m_marginWidth(-1) 51 , m_marginHeight(-1) 52 , m_viewSource(false) 53{ 54} 55 56bool HTMLFrameElementBase::isURLAllowed() const 57{ 58 if (m_URL.isEmpty()) 59 return true; 60 61 const KURL& completeURL = document()->completeURL(m_URL); 62 63 if (protocolIsJavaScript(completeURL)) { 64 Document* contentDoc = this->contentDocument(); 65 if (contentDoc && !ScriptController::canAccessFromCurrentOrigin(contentDoc->frame())) 66 return false; 67 } 68 69 Frame* parentFrame = document()->frame(); 70 if (parentFrame) 71 return parentFrame->isURLAllowed(completeURL); 72 73 return true; 74} 75 76void HTMLFrameElementBase::openURL(bool lockHistory, bool lockBackForwardList) 77{ 78 if (!isURLAllowed()) 79 return; 80 81 if (m_URL.isEmpty()) 82 m_URL = blankURL().string(); 83 84 Frame* parentFrame = document()->frame(); 85 if (!parentFrame) 86 return; 87 88 parentFrame->loader()->subframeLoader()->requestFrame(this, m_URL, m_frameName, lockHistory, lockBackForwardList); 89 if (contentFrame()) 90 contentFrame()->setInViewSourceMode(viewSourceMode()); 91} 92 93void HTMLFrameElementBase::parseAttribute(const QualifiedName& name, const AtomicString& value) 94{ 95 if (name == srcdocAttr) 96 setLocation("about:srcdoc"); 97 else if (name == srcAttr && !fastHasAttribute(srcdocAttr)) 98 setLocation(stripLeadingAndTrailingHTMLSpaces(value)); 99 else if (isIdAttributeName(name)) { 100 // Important to call through to base for the id attribute so the hasID bit gets set. 101 HTMLFrameOwnerElement::parseAttribute(name, value); 102 m_frameName = value; 103 } else if (name == nameAttr) { 104 m_frameName = value; 105 // FIXME: If we are already attached, this doesn't actually change the frame's name. 106 // FIXME: If we are already attached, this doesn't check for frame name 107 // conflicts and generate a unique frame name. 108 } else if (name == marginwidthAttr) { 109 m_marginWidth = value.toInt(); 110 // FIXME: If we are already attached, this has no effect. 111 } else if (name == marginheightAttr) { 112 m_marginHeight = value.toInt(); 113 // FIXME: If we are already attached, this has no effect. 114 } else if (name == scrollingAttr) { 115 // Auto and yes both simply mean "allow scrolling." No means "don't allow scrolling." 116 if (equalIgnoringCase(value, "auto") || equalIgnoringCase(value, "yes")) 117 m_scrolling = document()->frameElementsShouldIgnoreScrolling() ? ScrollbarAlwaysOff : ScrollbarAuto; 118 else if (equalIgnoringCase(value, "no")) 119 m_scrolling = ScrollbarAlwaysOff; 120 // FIXME: If we are already attached, this has no effect. 121#if ENABLE(VIEWSOURCE_ATTRIBUTE) 122 } else if (name == viewsourceAttr) { 123 m_viewSource = !value.isNull(); 124 if (contentFrame()) 125 contentFrame()->setInViewSourceMode(viewSourceMode()); 126#endif 127 } else if (name == onbeforeloadAttr) 128 setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, name, value)); 129 else if (name == onbeforeunloadAttr) { 130 // FIXME: should <frame> elements have beforeunload handlers? 131 setAttributeEventListener(eventNames().beforeunloadEvent, createAttributeEventListener(this, name, value)); 132 } else 133 HTMLFrameOwnerElement::parseAttribute(name, value); 134} 135 136void HTMLFrameElementBase::setNameAndOpenURL() 137{ 138 m_frameName = getNameAttribute(); 139 if (m_frameName.isNull()) 140 m_frameName = getIdAttribute(); 141 openURL(); 142} 143 144Node::InsertionNotificationRequest HTMLFrameElementBase::insertedInto(ContainerNode* insertionPoint) 145{ 146 HTMLFrameOwnerElement::insertedInto(insertionPoint); 147 if (insertionPoint->inDocument()) 148 return InsertionShouldCallDidNotifySubtreeInsertions; 149 return InsertionDone; 150} 151 152void HTMLFrameElementBase::didNotifySubtreeInsertions(ContainerNode*) 153{ 154 if (!inDocument()) 155 return; 156 157 // DocumentFragments don't kick of any loads. 158 if (!document()->frame()) 159 return; 160 161 if (!SubframeLoadingDisabler::canLoadFrame(this)) 162 return; 163 164 // JavaScript in src=javascript: and beforeonload can access the renderer 165 // during attribute parsing *before* the normal parser machinery would 166 // attach the element. To support this, we lazyAttach here, but only 167 // if we don't already have a renderer (if we're inserted 168 // as part of a DocumentFragment, insertedInto from an earlier element 169 // could have forced a style resolve and already attached us). 170 if (!renderer()) 171 lazyAttach(DoNotSetAttached); 172 setNameAndOpenURL(); 173} 174 175void HTMLFrameElementBase::attach(const AttachContext& context) 176{ 177 HTMLFrameOwnerElement::attach(context); 178 179 if (RenderPart* part = renderPart()) { 180 if (Frame* frame = contentFrame()) 181 part->setWidget(frame->view()); 182 } 183} 184 185KURL HTMLFrameElementBase::location() const 186{ 187 if (fastHasAttribute(srcdocAttr)) 188 return KURL(ParsedURLString, "about:srcdoc"); 189 return document()->completeURL(getAttribute(srcAttr)); 190} 191 192void HTMLFrameElementBase::setLocation(const String& str) 193{ 194 Settings* settings = document()->settings(); 195 if (settings && settings->needsAcrobatFrameReloadingQuirk() && m_URL == str) 196 return; 197 198 m_URL = AtomicString(str); 199 200 if (inDocument()) 201 openURL(false, false); 202} 203 204bool HTMLFrameElementBase::supportsFocus() const 205{ 206 return true; 207} 208 209void HTMLFrameElementBase::setFocus(bool received) 210{ 211 HTMLFrameOwnerElement::setFocus(received); 212 if (Page* page = document()->page()) { 213 if (received) 214 page->focusController()->setFocusedFrame(contentFrame()); 215 else if (page->focusController()->focusedFrame() == contentFrame()) // Focus may have already been given to another frame, don't take it away. 216 page->focusController()->setFocusedFrame(0); 217 } 218} 219 220bool HTMLFrameElementBase::isURLAttribute(const Attribute& attribute) const 221{ 222 return attribute.name() == srcAttr || HTMLFrameOwnerElement::isURLAttribute(attribute); 223} 224 225bool HTMLFrameElementBase::isHTMLContentAttribute(const Attribute& attribute) const 226{ 227 return attribute.name() == srcdocAttr || HTMLFrameOwnerElement::isHTMLContentAttribute(attribute); 228} 229 230int HTMLFrameElementBase::width() 231{ 232 document()->updateLayoutIgnorePendingStylesheets(); 233 if (!renderBox()) 234 return 0; 235 return renderBox()->width(); 236} 237 238int HTMLFrameElementBase::height() 239{ 240 document()->updateLayoutIgnorePendingStylesheets(); 241 if (!renderBox()) 242 return 0; 243 return renderBox()->height(); 244} 245 246} // namespace WebCore 247