SVN commit 1200140 by orlovich: For stuff like cross-frame form submission, we want to use the HTML5 "can navigate" algorithm and not normal XSS checks. Makes the new mail reader on libero.it get further (Probably will need more adjustment, though) M +1 -1 khtml_ext.cpp M +55 -9 khtml_part.cpp M +6 -0 khtmlpart_p.h --- trunk/KDE/kdelibs/khtml/khtml_ext.cpp #1200139:1200140 @@ -992,7 +992,7 @@ KParts::BrowserHostExtension* KHTMLPartBrowserHostExtension::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &frame ) { - KHTMLPart *parentPart = m_part->findFrameParent(callingPart, frame); + KHTMLPart *parentPart = m_part->d->findFrameParent(callingPart, frame, 0, true /* navigation*/); if (parentPart) return parentPart->browserHostExtension(); return 0; --- trunk/KDE/kdelibs/khtml/khtml_part.cpp #1200139:1200140 @@ -5166,36 +5166,46 @@ KHTMLPart * KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame ) { + return d->findFrameParent(callingPart, f, childFrame, false); +} + +KHTMLPart* KHTMLPartPrivate::findFrameParent(KParts::ReadOnlyPart* callingPart, + const QString& f, khtml::ChildFrame **childFrame, bool checkForNavigation) +{ #ifdef DEBUG_FINDFRAME - kDebug(6050) << this << "URL =" << url() << "name =" << objectName() << "findFrameParent(" << f << ")"; + kDebug(6050) << q << "URL =" << q->url() << "name =" << q->objectName() << "findFrameParent(" << f << ")"; #endif // Check access KHTMLPart* const callingHtmlPart = dynamic_cast(callingPart); - if (!checkFrameAccess(callingHtmlPart)) + if (!checkForNavigation && !q->checkFrameAccess(callingHtmlPart)) return 0; - if (!childFrame && !parentPart() && (objectName() == f)) - return this; + if (!childFrame && !q->parentPart() && (q->objectName() == f)) { + if (!checkForNavigation || callingHtmlPart->d->canNavigate(q)) + return q; + } - FrameIt it = d->m_frames.find( f ); - const FrameIt end = d->m_frames.end(); + FrameIt it = m_frames.find( f ); + const FrameIt end = m_frames.end(); if ( it != end ) { #ifdef DEBUG_FINDFRAME kDebug(6050) << "FOUND!"; #endif + if (!checkForNavigation || callingHtmlPart->d->canNavigate((*it)->m_part.data())) { if (childFrame) *childFrame = *it; - return this; + return q; } + } - it = d->m_frames.begin(); + it = m_frames.begin(); for (; it != end; ++it ) { if ( KHTMLPart* p = qobject_cast((*it)->m_part.data()) ) { - KHTMLPart* const frameParent = p->findFrameParent(callingPart, f, childFrame); + KHTMLPart* const frameParent = p->d->findFrameParent(callingPart, f, childFrame, checkForNavigation); if (frameParent) return frameParent; } @@ -5203,7 +5213,43 @@ return 0; } +KHTMLPart* KHTMLPartPrivate::top() +{ + KHTMLPart* t = q; + while (t->parentPart()) + t = t->parentPart(); + return t; +} +bool KHTMLPartPrivate::canNavigate(KParts::ReadOnlyPart* bCand) +{ + KHTMLPart* b = qobject_cast(bCand); + assert(b); + + // HTML5 gives conditions for this (a) being able to navigate b + + // 1) Same domain + if (q->checkFrameAccess(b)) + return true; + + // 2) A is nested, with B its top + if (q->parentPart() && top() == b) + return true; + + // 3) B is 'auxilary' -- window.open with opener, + // and A can navigate B's opener + if (b->opener() && canNavigate(b->opener())) + return true; + + // 4) B is not top-level, but an ancestor of it has same origin as A + for (KHTMLPart* anc = b->parentPart(); anc; anc = anc->parentPart()) { + if (anc->checkFrameAccess(q)) + return true; + } + + return false; +} + KHTMLPart *KHTMLPart::findFrame( const QString &f ) { khtml::ChildFrame *childFrame; --- trunk/KDE/kdelibs/khtml/khtmlpart_p.h #1200139:1200140 @@ -453,6 +453,12 @@ void renameFrameForContainer(DOM::HTMLPartContainerElementImpl* cont, const QString& newName); + KHTMLPart* findFrameParent(KParts::ReadOnlyPart* callingPart, const QString& f, + khtml::ChildFrame **childFrame, bool checkForNavigation); + + bool canNavigate(KParts::ReadOnlyPart* b); + KHTMLPart* top(); + // Check whether the frame is fully loaded. // The return value doesn't consider any pending redirections. // If the return value is true, however, pendingRedirections will