[prev in list] [next in list] [prev in thread] [next in thread]
List: kfm-devel
Subject: Re: gmail problem investigated: frame onload
From: Allan Sandfeld Jensen <kde () carewolf ! com>
Date: 2004-10-04 16:53:24
Message-ID: 200410041853.24905.kde () carewolf ! com
[Download RAW message or body]
On Monday 04 October 2004 16:41, David Faure wrote:
> With Rainder Endres' help, I managed to track down the reason gmail won't
> load. The onload event listener for frames and iframes is registered on the
> wrong body: the main body instead of the frame's body. Which means only one
> gets executed, and the JS code waits for ever.
>
> Testcase [gmail uses iframes, but it's the same with frames] :
>
> ==> blank.html <==
> Hello world
>
> ==> frameset.html <==
> <html>
> <frameset rows="*,*,*">
> <frame name="main" src="blank.html" onload="alert('loaded main')">
> <frame name="blank" src="blank.html" onload="alert('loaded blank')">
> </frameset>
> </html>
>
> The problem is HTMLFrameElementImpl::parseAttribute (for ATTR_ONLOAD).
> The code says:
> static_cast<HTMLDocumentImpl*>( getDocument() )->body()->
> setHTMLEventListener(EventImpl::LOAD_EVENT,
>
> getDocument()->createHTMLEventListener(attr->value().string(),"onload"));
> And this obviously finds the main <body> element, since getDocument() for
> the frame element finds the main document.
>
> Did this ever work in KHTML? I thought it did, but looking at the code, I
> fail to see how. Since the attributes are parsed before the frame is
> "attached", so there is no KHTMLPart for the frame yet... i.e. no way to
> find the right document (or body) from that code. So do we need to store
> the value of the load and unload listeners until attach? We would then need
> to have some code somewhere that sets the listener on the frame's body when
> creating it..... I'm working now on a patch that attempts to do that.
I've been looking at how Safari handles it, and have come up with the attached
patch. It works on your test example, but I do not have a gmail-account to
test with.
`Allan
["safari.diff" (text/x-diff)]
Index: html/html_baseimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/html/html_baseimpl.cpp,v
retrieving revision 1.198
diff -u -3 -p -r1.198 html_baseimpl.cpp
--- html/html_baseimpl.cpp 16 Apr 2004 22:48:25 -0000 1.198
+++ html/html_baseimpl.cpp 4 Oct 2004 16:44:28 -0000
@@ -280,14 +280,12 @@ void HTMLFrameElementImpl::parseAttribut
// when attached, has no effect
break;
case ATTR_ONLOAD:
- static_cast<HTMLDocumentImpl*>( getDocument() )->body()
- ->setHTMLEventListener(EventImpl::LOAD_EVENT,
- getDocument()->createHTMLEventListener(attr->value().string(),"onload"));
+ setHTMLEventListener(EventImpl::LOAD_EVENT,
+ \
getDocument()->createHTMLEventListener(attr->value().string(),"onload")); break;
case ATTR_ONUNLOAD:
- static_cast<HTMLDocumentImpl*>( getDocument() )->body()
- ->setHTMLEventListener(EventImpl::UNLOAD_EVENT,
- getDocument()->createHTMLEventListener(attr->value().string(),"onunload"));
+ setHTMLEventListener(EventImpl::UNLOAD_EVENT,
+ \
getDocument()->createHTMLEventListener(attr->value().string(),"onunload")); break;
default:
Index: xml/dom_docimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_docimpl.cpp,v
retrieving revision 1.292
diff -u -3 -p -r1.292 dom_docimpl.cpp
--- xml/dom_docimpl.cpp 19 Sep 2004 13:33:06 -0000 1.292
+++ xml/dom_docimpl.cpp 4 Oct 2004 16:44:29 -0000
@@ -50,6 +50,7 @@
#include "rendering/render_replaced.h"
#include "rendering/render_arena.h"
#include "rendering/render_layer.h"
+#include "rendering/render_frames.h"
#include "khtmlview.h"
#include "khtml_part.h"
@@ -1670,7 +1671,7 @@ NodeImpl::Id DocumentImpl::getId( NodeIm
QConstString n(_name->s, _name->l);
bool cs = true; // case sensitive
if (_type != NodeImpl::NamespaceId) {
- if (_nsURI)
+ if (_nsURI)
nsid = getId( NodeImpl::NamespaceId, 0, 0, _nsURI, false, false, 0 ) << \
16;
// Each document maintains a mapping of tag name -> id for every tag name \
encountered @@ -2271,6 +2272,58 @@ void DocumentImpl::setDecoderCodec(const
m_decoderMibEnum = codec->mibEnum();
}
+ElementImpl *DocumentImpl::ownerElement()
+{
+ KHTMLView *childView = view();
+ if (!childView)
+ return 0;
+ KHTMLPart *childPart = childView->part();
+ if (!childPart)
+ return 0;
+ KHTMLPart *parent = childPart->parentPart();
+ if (!parent)
+ return 0;
+ ChildFrame *childFrame = parent->frame(childPart);
+ if (!childFrame)
+ return 0;
+ RenderPart *renderPart = childFrame->m_frame;
+ if (!renderPart)
+ return 0;
+ return static_cast<ElementImpl *>(renderPart->element());
+}
+
+DOMString DocumentImpl::domain() const
+{
+ if ( m_domain.isEmpty() ) // not set yet (we set it on demand to save time and \
space) + m_domain = KURL(URL()).host(); // Initially set to the host
+ return m_domain;
+}
+
+void DocumentImpl::setDomain(const DOMString &newDomain, bool force /*=false*/)
+{
+ if ( force ) {
+ m_domain = newDomain;
+ return;
+ }
+ if ( m_domain.isEmpty() ) // not set yet (we set it on demand to save time and \
space) + m_domain = KURL(URL()).host(); // Initially set to the host
+
+ // Both NS and IE specify that changing the domain is only allowed when
+ // the new domain is a suffix of the old domain.
+ int oldLength = m_domain.length();
+ int newLength = newDomain.length();
+ if ( newLength < oldLength ) // e.g. newDomain=kde.org (7) and \
m_domain=www.kde.org (11) + {
+ DOMString test = m_domain.copy();
+ if ( test[oldLength - newLength - 1] == '.' ) // Check that it's a \
subdomain, not e.g. "de.org" + {
+ test.remove( 0, oldLength - newLength ); // now test is "kde.org" from \
m_domain + if ( test == newDomain ) // and we check that \
it's the same thing as newDomain + m_domain = newDomain;
+ }
+ }
+}
+
DOMString DocumentImpl::toString() const
{
DOMString result;
Index: xml/dom_docimpl.h
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_docimpl.h,v
retrieving revision 1.133
diff -u -3 -p -r1.133 dom_docimpl.h
--- xml/dom_docimpl.h 19 Sep 2004 13:33:06 -0000 1.133
+++ xml/dom_docimpl.h 4 Oct 2004 16:44:29 -0000
@@ -426,6 +426,13 @@ public:
*/
void processHttpEquiv(const DOMString &equiv, const DOMString &content);
+ // Returns the owning element in the parent document.
+ // Returns 0 if this is the top level document.
+ ElementImpl *ownerElement();
+
+ DOMString domain() const;
+ void setDomain( const DOMString &newDomain, bool force = false ); // not part of \
the DOM +
bool isURLAllowed(const QString& url) const;
DOMString toString() const;
@@ -519,6 +526,9 @@ protected:
int m_decoderMibEnum;
khtml::RenderArena* m_renderArena;
+
+private:
+ mutable DOMString m_domain;
};
class DocumentFragmentImpl : public NodeBaseImpl
Index: xml/dom_nodeimpl.cpp
===================================================================
RCS file: /home/kde/kdelibs/khtml/xml/dom_nodeimpl.cpp,v
retrieving revision 1.238
diff -u -3 -p -r1.238 dom_nodeimpl.cpp
--- xml/dom_nodeimpl.cpp 8 Sep 2004 12:59:38 -0000 1.238
+++ xml/dom_nodeimpl.cpp 4 Oct 2004 16:44:29 -0000
@@ -323,10 +323,14 @@ void NodeImpl::addEventListener(int id,
m_regdListeners->setAutoDelete(true);
}
- // remove existing ones of the same type - ### is this correct (or do we ignore \
the new one?) + listener->ref();
+
+ // remove existing identical listener set with identical arguments - the DOM2
+ // spec says that "duplicate instances are discarded" in this case.
removeEventListener(id,listener,useCapture);
m_regdListeners->append(rl);
+ listener->deref();
}
void NodeImpl::removeEventListener(int id, EventListener *listener, bool useCapture)
@@ -491,6 +495,28 @@ void NodeImpl::dispatchWindowEvent(int _
dispatchGenericEvent( evt, exceptioncode );
if (!evt->defaultPrevented() && doc->document())
doc->document()->defaultEventHandler(evt);
+
+ if (_id == EventImpl::LOAD_EVENT && !evt->propagationStopped() && \
doc->document()) { + // For onload events, send them to the enclosing frame \
only. + // This is a DOM extension and is independent of bubbling/capturing \
rules of + // the DOM. You send the event only to the enclosing frame. It \
does not + // bubble through the parent document.
+ DOM::ElementImpl* elt = doc->document()->ownerElement();
+ if (elt && (elt->getDocument()->domain().isNull() ||
+ elt->getDocument()->domain() == doc->document()->domain())) {
+ // We also do a security check, since we don't want to allow the \
enclosing + // iframe to see loads of child documents in other domains.
+ evt->setCurrentTarget(elt);
+
+ // Capturing first.
+ elt->handleLocalEvents(evt,true);
+
+ // Bubbling second.
+ if (!evt->propagationStopped())
+ elt->handleLocalEvents(evt,false);
+ }
+ }
+
doc->deref();
evt->deref();
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic