• Skip to content
  • Skip to link menu
KDE 4.7 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KHTML

khtml_part.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00004  *                     1999 Lars Knoll <knoll@kde.org>
00005  *                     1999 Antti Koivisto <koivisto@kde.org>
00006  *                     2000 Simon Hausmann <hausmann@kde.org>
00007  *                     2000 Stefan Schimanski <1Stein@gmx.de>
00008  *                     2001-2005 George Staikos <staikos@kde.org>
00009  *                     2001-2003 Dirk Mueller <mueller@kde.org>
00010  *                     2000-2005 David Faure <faure@kde.org>
00011  *                     2002 Apple Computer, Inc.
00012  *                     2010 Maksim Orlovich (maksim@kde.org)
00013  *
00014  * This library is free software; you can redistribute it and/or
00015  * modify it under the terms of the GNU Library General Public
00016  * License as published by the Free Software Foundation; either
00017  * version 2 of the License, or (at your option) any later version.
00018  *
00019  * This library is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00022  * Library General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU Library General Public License
00025  * along with this library; see the file COPYING.LIB.  If not, write to
00026  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00027  * Boston, MA 02110-1301, USA.
00028  */
00029 
00030 //#define SPEED_DEBUG
00031 #include "khtml_part.h"
00032 
00033 #include "ui_htmlpageinfo.h"
00034 
00035 #include "khtmlviewbar.h"
00036 #include "khtml_pagecache.h"
00037 
00038 #include "dom/dom_string.h"
00039 #include "dom/dom_element.h"
00040 #include "dom/dom_exception.h"
00041 #include "dom/html_document.h"
00042 #include "dom/dom2_range.h"
00043 #include "editing/editor.h"
00044 #include "html/html_documentimpl.h"
00045 #include "html/html_baseimpl.h"
00046 #include "html/html_objectimpl.h"
00047 #include "html/html_miscimpl.h"
00048 #include "html/html_imageimpl.h"
00049 #include "imload/imagemanager.h"
00050 #include "rendering/render_text.h"
00051 #include "rendering/render_frames.h"
00052 #include "rendering/render_layer.h"
00053 #include "rendering/render_position.h"
00054 #include "misc/loader.h"
00055 #include "misc/khtml_partaccessor.h"
00056 #include "xml/dom2_eventsimpl.h"
00057 #include "xml/dom2_rangeimpl.h"
00058 #include "xml/xml_tokenizer.h"
00059 #include "css/cssstyleselector.h"
00060 #include "css/csshelper.h"
00061 using namespace DOM;
00062 
00063 #include "khtmlview.h"
00064 #include <kparts/partmanager.h>
00065 #include <kparts/browseropenorsavequestion.h>
00066 #include <kacceleratormanager.h>
00067 #include "ecma/kjs_proxy.h"
00068 #include "ecma/kjs_window.h"
00069 #include "khtml_settings.h"
00070 #include "kjserrordlg.h"
00071 
00072 #include <kjs/function.h>
00073 #include <kjs/interpreter.h>
00074 
00075 #include <sys/types.h>
00076 #include <assert.h>
00077 #include <unistd.h>
00078 
00079 #include <config.h>
00080 
00081 #include <kstandarddirs.h>
00082 #include <kstringhandler.h>
00083 #include <kio/job.h>
00084 #include <kio/jobuidelegate.h>
00085 #include <kio/global.h>
00086 #include <kio/netaccess.h>
00087 #include <kio/hostinfo_p.h>
00088 #include <kprotocolmanager.h>
00089 #include <kdebug.h>
00090 #include <kicon.h>
00091 #include <kiconloader.h>
00092 #include <klocale.h>
00093 #include <kmessagebox.h>
00094 #include <kstandardaction.h>
00095 #include <kstandardguiitem.h>
00096 #include <kactioncollection.h>
00097 #include <kfiledialog.h>
00098 #include <kmimetypetrader.h>
00099 #include <ktemporaryfile.h>
00100 #include <kglobalsettings.h>
00101 #include <ktoolinvocation.h>
00102 #include <kauthorized.h>
00103 #include <kparts/browserinterface.h>
00104 #include <kparts/scriptableextension.h>
00105 #include <kde_file.h>
00106 #include <kactionmenu.h>
00107 #include <ktoggleaction.h>
00108 #include <kcodecaction.h>
00109 #include <kselectaction.h>
00110 
00111 #include <ksslinfodialog.h>
00112 #include <ksslsettings.h>
00113 
00114 #include <kfileitem.h>
00115 #include <kurifilter.h>
00116 #include <kstatusbar.h>
00117 #include <kurllabel.h>
00118 
00119 #include <QtGui/QClipboard>
00120 #include <QtGui/QToolTip>
00121 #include <QtCore/QFile>
00122 #include <QtCore/QMetaEnum>
00123 #include <QtGui/QTextDocument>
00124 #include <QtCore/QDate>
00125 #include <QtNetwork/QSslCertificate>
00126 
00127 #include "khtmlpart_p.h"
00128 #include "khtml_iface.h"
00129 #include "kpassivepopup.h"
00130 #include "kmenu.h"
00131 #include "rendering/render_form.h"
00132 #include <kwindowsystem.h>
00133 #include <kconfiggroup.h>
00134 
00135 #include "ecma/debugger/debugwindow.h"
00136 
00137 // SVG
00138 #include <svg/SVGDocument.h>
00139 
00140 bool KHTMLPartPrivate::s_dnsInitialised = false;
00141 
00142 // DNS prefetch settings
00143 static const int sMaxDNSPrefetchPerPage = 42;
00144 static const int sDNSPrefetchTimerDelay = 200;
00145 static const int sDNSTTLSeconds = 400;
00146 static const int sDNSCacheSize = 500;
00147 
00148 
00149 namespace khtml {
00150 
00151     class PartStyleSheetLoader : public CachedObjectClient
00152     {
00153     public:
00154         PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
00155         {
00156             m_part = part;
00157             m_cachedSheet = dl->requestStyleSheet(url, QString(), "text/css",
00158                                                   true /* "user sheet" */);
00159             if (m_cachedSheet)
00160                 m_cachedSheet->ref( this );
00161         }
00162         virtual ~PartStyleSheetLoader()
00163         {
00164             if ( m_cachedSheet ) m_cachedSheet->deref(this);
00165         }
00166         virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet, const DOM::DOMString &, const DOM::DOMString &/*mimetype*/)
00167         {
00168           if ( m_part )
00169             m_part->setUserStyleSheet( sheet.string() );
00170 
00171             delete this;
00172         }
00173         virtual void error( int, const QString& ) {
00174           delete this;
00175         }
00176         QPointer<KHTMLPart> m_part;
00177         khtml::CachedCSSStyleSheet *m_cachedSheet;
00178     };
00179 }
00180 
00181 KHTMLPart::KHTMLPart( QWidget *parentWidget, QObject *parent, GUIProfile prof )
00182 : KParts::ReadOnlyPart( parent )
00183 {
00184     d = 0;
00185     KHTMLGlobal::registerPart( this );
00186     setComponentData( KHTMLGlobal::componentData(), false );
00187     init( new KHTMLView( this, parentWidget ), prof );
00188 }
00189 
00190 KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, GUIProfile prof )
00191 : KParts::ReadOnlyPart( parent )
00192 {
00193     d = 0;
00194     KHTMLGlobal::registerPart( this );
00195     setComponentData( KHTMLGlobal::componentData(), false );
00196     assert( view );
00197     if (!view->part())
00198         view->setPart( this );
00199     init( view, prof );
00200 }
00201 
00202 void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
00203 {
00204   if ( prof == DefaultGUI )
00205     setXMLFile( "khtml.rc" );
00206   else if ( prof == BrowserViewGUI )
00207     setXMLFile( "khtml_browser.rc" );
00208 
00209   d = new KHTMLPartPrivate(this, parent());
00210 
00211   d->m_view = view;
00212 
00213   if (!parentPart()) {
00214       QWidget *widget = new QWidget( view->parentWidget() );
00215       widget->setObjectName("khtml_part_widget");
00216       QVBoxLayout *layout = new QVBoxLayout( widget );
00217       layout->setContentsMargins( 0, 0, 0, 0 );
00218       layout->setSpacing( 0 );
00219       widget->setLayout( layout );
00220 
00221       d->m_topViewBar = new KHTMLViewBar( KHTMLViewBar::Top, d->m_view, widget );
00222       d->m_bottomViewBar = new KHTMLViewBar( KHTMLViewBar::Bottom, d->m_view, widget );
00223 
00224       layout->addWidget( d->m_topViewBar );
00225       layout->addWidget( d->m_view );
00226       layout->addWidget( d->m_bottomViewBar );
00227       setWidget( widget );
00228       widget->setFocusProxy( d->m_view );
00229   } else {
00230       setWidget( view );
00231   }
00232 
00233   d->m_guiProfile = prof;
00234   d->m_extension = new KHTMLPartBrowserExtension( this );
00235   d->m_extension->setObjectName( "KHTMLBrowserExtension" );
00236   d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
00237   d->m_statusBarExtension = new KParts::StatusBarExtension( this );
00238   d->m_scriptableExtension = new KJS::KHTMLPartScriptable( this );
00239   new KHTMLTextExtension( this );
00240   new KHTMLHtmlExtension( this );
00241   d->m_statusBarPopupLabel = 0L;
00242   d->m_openableSuppressedPopups = 0;
00243 
00244   d->m_paLoadImages = 0;
00245   d->m_paDebugScript = 0;
00246   d->m_bMousePressed = false;
00247   d->m_bRightMousePressed = false;
00248   d->m_bCleared = false;
00249 
00250   if ( prof == BrowserViewGUI ) {
00251     d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), this );
00252     actionCollection()->addAction( "viewDocumentSource", d->m_paViewDocument );
00253     connect( d->m_paViewDocument, SIGNAL( triggered( bool ) ), this, SLOT( slotViewDocumentSource() ) );
00254     if (!parentPart()) {
00255         d->m_paViewDocument->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_U) );
00256     }
00257 
00258     d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), this );
00259     actionCollection()->addAction( "viewFrameSource", d->m_paViewFrame );
00260     connect( d->m_paViewFrame, SIGNAL( triggered( bool ) ), this, SLOT( slotViewFrameSource() ) );
00261     if (!parentPart()) {
00262         d->m_paViewFrame->setShortcut( QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_U) );
00263     }
00264 
00265     d->m_paViewInfo = new KAction( i18n( "View Document Information" ), this );
00266     actionCollection()->addAction( "viewPageInfo", d->m_paViewInfo );
00267     if (!parentPart()) {
00268         d->m_paViewInfo->setShortcut( QKeySequence(Qt::CTRL+Qt::Key_I) );
00269     }
00270     connect( d->m_paViewInfo, SIGNAL( triggered( bool ) ), this, SLOT( slotViewPageInfo() ) );
00271 
00272     d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), this );
00273     actionCollection()->addAction( "saveBackground", d->m_paSaveBackground );
00274     connect( d->m_paSaveBackground, SIGNAL( triggered( bool ) ), this, SLOT( slotSaveBackground() ) );
00275 
00276     d->m_paSaveDocument = actionCollection()->addAction( KStandardAction::SaveAs, "saveDocument",
00277                                                        this, SLOT( slotSaveDocument() ) );
00278     if ( parentPart() )
00279         d->m_paSaveDocument->setShortcuts( KShortcut() ); // avoid clashes
00280 
00281     d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), this );
00282     actionCollection()->addAction( "saveFrame", d->m_paSaveFrame );
00283     connect( d->m_paSaveFrame, SIGNAL( triggered( bool ) ), this, SLOT( slotSaveFrame() ) );
00284   } else {
00285     d->m_paViewDocument = 0;
00286     d->m_paViewFrame = 0;
00287     d->m_paViewInfo = 0;
00288     d->m_paSaveBackground = 0;
00289     d->m_paSaveDocument = 0;
00290     d->m_paSaveFrame = 0;
00291   }
00292 
00293   d->m_paSecurity = new KAction( i18n( "SSL" ), this );
00294   actionCollection()->addAction( "security", d->m_paSecurity );
00295   connect( d->m_paSecurity, SIGNAL( triggered( bool ) ), this, SLOT( slotSecurity() ) );
00296 
00297   d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), this );
00298   actionCollection()->addAction( "debugRenderTree", d->m_paDebugRenderTree );
00299   connect( d->m_paDebugRenderTree, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugRenderTree() ) );
00300 
00301   d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), this );
00302   actionCollection()->addAction( "debugDOMTree", d->m_paDebugDOMTree );
00303   connect( d->m_paDebugDOMTree, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugDOMTree() ) );
00304 
00305   KAction* paDebugFrameTree = new KAction( i18n( "Print frame tree to STDOUT" ), this );
00306   actionCollection()->addAction( "debugFrameTree", paDebugFrameTree );
00307   connect( paDebugFrameTree, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugFrameTree() ) );
00308 
00309   d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), this );
00310   actionCollection()->addAction( "stopAnimations", d->m_paStopAnimations );
00311   connect( d->m_paStopAnimations, SIGNAL( triggered( bool ) ), this, SLOT( slotStopAnimations() ) );
00312 
00313   d->m_paSetEncoding = new KCodecAction( KIcon("character-set"), i18n( "Set &Encoding" ), this, true );
00314   actionCollection()->addAction( "setEncoding", d->m_paSetEncoding );
00315 //   d->m_paSetEncoding->setDelayed( false );
00316 
00317   connect( d->m_paSetEncoding, SIGNAL(triggered(const QString&)), this, SLOT( slotSetEncoding(const QString &)));
00318   connect( d->m_paSetEncoding, SIGNAL(triggered(KEncodingDetector::AutoDetectScript)), this, SLOT( slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript)));
00319 
00320   if ( KGlobal::config()->hasGroup( "HTML Settings" ) ) {
00321     KConfigGroup config( KGlobal::config(), "HTML Settings" );
00322 
00323     d->m_autoDetectLanguage = static_cast<KEncodingDetector::AutoDetectScript>(config.readEntry( "AutomaticDetectionLanguage", /*static_cast<int>(language) */0));
00324     if (d->m_autoDetectLanguage==KEncodingDetector::None) {
00325       const QByteArray name = KGlobal::locale()->encoding().toLower();
00326 //       kWarning() << "00000000 ";
00327       if (name.endsWith("1251")||name.startsWith("koi")||name=="iso-8859-5")
00328         d->m_autoDetectLanguage=KEncodingDetector::Cyrillic;
00329       else if (name.endsWith("1256")||name=="iso-8859-6")
00330         d->m_autoDetectLanguage=KEncodingDetector::Arabic;
00331       else if (name.endsWith("1257")||name=="iso-8859-13"||name=="iso-8859-4")
00332         d->m_autoDetectLanguage=KEncodingDetector::Baltic;
00333       else if (name.endsWith("1250")|| name=="ibm852" || name=="iso-8859-2" || name=="iso-8859-3" )
00334         d->m_autoDetectLanguage=KEncodingDetector::CentralEuropean;
00335       else if (name.endsWith("1253")|| name=="iso-8859-7" )
00336         d->m_autoDetectLanguage=KEncodingDetector::Greek;
00337       else if (name.endsWith("1255")|| name=="iso-8859-8" || name=="iso-8859-8-i" )
00338         d->m_autoDetectLanguage=KEncodingDetector::Hebrew;
00339       else if (name=="jis7" || name=="eucjp" || name=="sjis"  )
00340         d->m_autoDetectLanguage=KEncodingDetector::Japanese;
00341       else if (name.endsWith("1254")|| name=="iso-8859-9" )
00342         d->m_autoDetectLanguage=KEncodingDetector::Turkish;
00343       else if (name.endsWith("1252")|| name=="iso-8859-1" || name=="iso-8859-15" )
00344         d->m_autoDetectLanguage=KEncodingDetector::WesternEuropean;
00345       else
00346         d->m_autoDetectLanguage=KEncodingDetector::SemiautomaticDetection;
00347 //         kWarning() << "0000000end " << d->m_autoDetectLanguage << " " << KGlobal::locale()->encodingMib();
00348     }
00349     d->m_paSetEncoding->setCurrentAutoDetectScript(d->m_autoDetectLanguage);
00350   }
00351 
00352   d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), this );
00353   actionCollection()->addAction( "useStylesheet", d->m_paUseStylesheet );
00354   connect( d->m_paUseStylesheet, SIGNAL( triggered( int ) ), this, SLOT( slotUseStylesheet() ) );
00355 
00356   if ( prof == BrowserViewGUI ) {
00357       d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, "format-font-size-more", i18n( "Enlarge Font" ), this );
00358       actionCollection()->addAction( "incFontSizes", d->m_paIncZoomFactor );
00359       connect(d->m_paIncZoomFactor, SIGNAL(triggered(bool)), SLOT( slotIncFontSizeFast() ));
00360       d->m_paIncZoomFactor->setWhatsThis( i18n( "<qt>Enlarge Font<br /><br />"
00361                                                 "Make the font in this window bigger. "
00362                             "Click and hold down the mouse button for a menu with all available font sizes.</qt>" ) );
00363 
00364       d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, "format-font-size-less", i18n( "Shrink Font" ), this );
00365       actionCollection()->addAction( "decFontSizes", d->m_paDecZoomFactor );
00366       connect(d->m_paDecZoomFactor, SIGNAL(triggered(bool)), SLOT( slotDecFontSizeFast() ));
00367       d->m_paDecZoomFactor->setWhatsThis( i18n( "<qt>Shrink Font<br /><br />"
00368                                                 "Make the font in this window smaller. "
00369                             "Click and hold down the mouse button for a menu with all available font sizes.</qt>" ) );
00370       if (!parentPart()) {
00371           // For framesets, this action also affects frames, so only
00372           // the frameset needs to define a shortcut for the action.
00373 
00374           // TODO: Why also CTRL+=?  Because of http://trolltech.com/developer/knowledgebase/524/?
00375           // Nobody else does it...
00376           d->m_paIncZoomFactor->setShortcut( KShortcut("CTRL++; CTRL+=") );
00377           d->m_paDecZoomFactor->setShortcut( QKeySequence(Qt::CTRL + Qt::Key_Minus) );
00378       }
00379   }
00380 
00381   d->m_paFind = actionCollection()->addAction( KStandardAction::Find, "find", this, SLOT( slotFind() ) );
00382   d->m_paFind->setWhatsThis( i18n( "<qt>Find text<br /><br />"
00383                                    "Shows a dialog that allows you to find text on the displayed page.</qt>" ) );
00384 
00385   d->m_paFindNext = actionCollection()->addAction( KStandardAction::FindNext, "findNext", this, SLOT( slotFindNext() ) );
00386   d->m_paFindNext->setWhatsThis( i18n( "<qt>Find next<br /><br />"
00387                                        "Find the next occurrence of the text that you "
00388                                        "have found using the <b>Find Text</b> function.</qt>" ) );
00389 
00390   d->m_paFindPrev = actionCollection()->addAction( KStandardAction::FindPrev, "findPrevious",
00391                                                    this, SLOT( slotFindPrev() ) );
00392   d->m_paFindPrev->setWhatsThis( i18n( "<qt>Find previous<br /><br />"
00393                                        "Find the previous occurrence of the text that you "
00394                                        "have found using the <b>Find Text</b> function.</qt>" ) );
00395 
00396   // These two actions aren't visible in the menus, but exist for the (configurable) shortcut
00397   d->m_paFindAheadText = new KAction( i18n("Find Text as You Type"), this );
00398   actionCollection()->addAction( "findAheadText", d->m_paFindAheadText );
00399   d->m_paFindAheadText->setShortcuts( KShortcut( '/' ) );
00400   d->m_paFindAheadText->setHelpText(i18n("This shortcut shows the find bar, for finding text in the displayed page. It cancels the effect of \"Find Links as You Type\", which sets the \"Find links only\" option."));
00401   connect( d->m_paFindAheadText, SIGNAL( triggered( bool ) ), this, SLOT( slotFindAheadText()) );
00402 
00403   d->m_paFindAheadLinks = new KAction( i18n("Find Links as You Type"), this );
00404   actionCollection()->addAction( "findAheadLink", d->m_paFindAheadLinks );
00405   // The issue is that it sets the (sticky) option FindLinksOnly, so
00406   // if you trigger this shortcut once by mistake, Esc and Ctrl+F will still have the option set.
00407   // Better let advanced users configure a shortcut for this advanced option
00408   //d->m_paFindAheadLinks->setShortcuts( KShortcut( '\'' ) );
00409   d->m_paFindAheadLinks->setHelpText(i18n("This shortcut shows the find bar, and sets the option \"Find links only\"."));
00410   connect( d->m_paFindAheadLinks, SIGNAL( triggered( bool ) ), this, SLOT( slotFindAheadLink() ) );
00411 
00412   if ( parentPart() )
00413   {
00414       d->m_paFind->setShortcuts( KShortcut() ); // avoid clashes
00415       d->m_paFindNext->setShortcuts( KShortcut() ); // avoid clashes
00416       d->m_paFindPrev->setShortcuts( KShortcut() ); // avoid clashes
00417       d->m_paFindAheadText->setShortcuts( KShortcut());
00418       d->m_paFindAheadLinks->setShortcuts( KShortcut());
00419   }
00420 
00421   d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), this );
00422   actionCollection()->addAction( "printFrame", d->m_paPrintFrame );
00423   d->m_paPrintFrame->setIcon( KIcon( "document-print-frame" ) );
00424   connect( d->m_paPrintFrame, SIGNAL( triggered( bool ) ), this, SLOT( slotPrintFrame() ) );
00425   d->m_paPrintFrame->setWhatsThis( i18n( "<qt>Print Frame<br /><br />"
00426                                          "Some pages have several frames. To print only a single frame, click "
00427                                          "on it and then use this function.</qt>" ) );
00428 
00429   // Warning: The name selectAll is used hardcoded by some 3rd parties to remove the
00430   // shortcut for selectAll so they do not get ambigous shortcuts. Renaming it
00431   // will either crash or render useless that workaround. It would be better
00432   // to use the name KStandardAction::name(KStandardAction::SelectAll) but we
00433   // can't for the same reason.
00434   d->m_paSelectAll = actionCollection()->addAction( KStandardAction::SelectAll, "selectAll",
00435                                                     this, SLOT( slotSelectAll() ) );
00436   if ( parentPart() ) // Only the frameset has the shortcut, but the slot uses the current frame.
00437       d->m_paSelectAll->setShortcuts( KShortcut() ); // avoid clashes
00438 
00439   d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"), this );
00440   actionCollection()->addAction( "caretMode", d->m_paToggleCaretMode );
00441   d->m_paToggleCaretMode->setShortcut( QKeySequence(Qt::Key_F7) );
00442   connect( d->m_paToggleCaretMode, SIGNAL( triggered( bool ) ), this, SLOT(slotToggleCaretMode()) );
00443   d->m_paToggleCaretMode->setChecked(isCaretMode());
00444   if (parentPart())
00445       d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes
00446 
00447   // set the default java(script) flags according to the current host.
00448   d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled();
00449   d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
00450   setDebugScript( d->m_settings->isJavaScriptDebugEnabled() );
00451   d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
00452   d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
00453 
00454   // Set the meta-refresh flag...
00455   d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
00456 
00457   KHTMLSettings::KSmoothScrollingMode ssm = d->m_settings->smoothScrolling();
00458   if (ssm == KHTMLSettings::KSmoothScrollingDisabled)
00459       d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled);
00460   else if (ssm == KHTMLSettings::KSmoothScrollingWhenEfficient)
00461       d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient);
00462   else
00463       d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled);
00464 
00465   if (d->m_bDNSPrefetchIsDefault && !onlyLocalReferences()) {
00466       KHTMLSettings::KDNSPrefetch dpm = d->m_settings->dnsPrefetch();
00467       if (dpm == KHTMLSettings::KDNSPrefetchDisabled)
00468           d->m_bDNSPrefetch = DNSPrefetchDisabled;
00469       else if (dpm == KHTMLSettings::KDNSPrefetchOnlyWWWAndSLD)
00470           d->m_bDNSPrefetch = DNSPrefetchOnlyWWWAndSLD;
00471       else
00472           d->m_bDNSPrefetch = DNSPrefetchEnabled;
00473   }
00474 
00475   if (!KHTMLPartPrivate::s_dnsInitialised && d->m_bDNSPrefetch != DNSPrefetchDisabled) {
00476       KIO::HostInfo::setCacheSize( sDNSCacheSize );
00477       KIO::HostInfo::setTTL( sDNSTTLSeconds );
00478       KHTMLPartPrivate::s_dnsInitialised = true;
00479   }
00480 
00481   // all shortcuts should only be active, when this part has focus
00482   foreach ( QAction *action, actionCollection ()->actions () ) {
00483       action->setShortcutContext ( Qt::WidgetWithChildrenShortcut );
00484   }
00485   actionCollection()->associateWidget(view);
00486 
00487   connect( view, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
00488 
00489   connect( this, SIGNAL( completed() ),
00490            this, SLOT( updateActions() ) );
00491   connect( this, SIGNAL( completed( bool ) ),
00492            this, SLOT( updateActions() ) );
00493   connect( this, SIGNAL( started( KIO::Job * ) ),
00494            this, SLOT( updateActions() ) );
00495 
00496   // #### FIXME: the process wide loader is going to signal every part about every loaded object.
00497   //      That's quite inefficient. Should be per-document-tree somehow. Even signaling to
00498   //      child parts that a request from an ancestor has loaded is inefficent..
00499   connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
00500            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
00501   connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
00502            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00503   connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
00504            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00505 
00506   connect ( &d->m_progressUpdateTimer, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
00507 
00508   findTextBegin(); //reset find variables
00509 
00510   connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
00511            this, SLOT( slotRedirect() ) );
00512 
00513   if (QDBusConnection::sessionBus().isConnected()) {
00514       new KHTMLPartIface(this); // our "adaptor"
00515     for (int i = 1; ; ++i)
00516       if (QDBusConnection::sessionBus().registerObject(QString("/KHTML/%1/widget").arg(i), this))
00517         break;
00518       else if (i == 0xffff)
00519         kFatal() << "Something is very wrong in KHTMLPart!";
00520   }
00521 
00522   if (prof == BrowserViewGUI && !parentPart())
00523       loadPlugins();
00524 
00525   // "khtml" catalog does not exist, our translations are in kdelibs.
00526   // removing this catalog from KGlobal::locale() prevents problems
00527   // with changing the language in applications at runtime -Thomas Reitelbach
00528   // DF: a better fix would be to set the right catalog name in the KComponentData!
00529   KGlobal::locale()->removeCatalog("khtml");
00530 }
00531 
00532 KHTMLPart::~KHTMLPart()
00533 {
00534   kDebug(6050) << this;
00535   KConfigGroup config( KGlobal::config(), "HTML Settings" );
00536   config.writeEntry( "AutomaticDetectionLanguage", int(d->m_autoDetectLanguage) );
00537 
00538   if (d->m_manager) { // the PartManager for this part's children
00539     d->m_manager->removePart(this);
00540   }
00541 
00542   slotWalletClosed();
00543   if (!parentPart()) { // only delete it if the top khtml_part closes
00544     removeJSErrorExtension();
00545   }
00546 
00547   stopAutoScroll();
00548   d->m_redirectionTimer.stop();
00549 
00550   if (!d->m_bComplete)
00551     closeUrl();
00552 
00553   disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
00554            this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
00555   disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
00556            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00557   disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
00558            this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
00559 
00560   clear();
00561   hide();
00562 
00563   if ( d->m_view )
00564   {
00565     d->m_view->m_part = 0;
00566   }
00567 
00568   // Have to delete this here since we forward declare it in khtmlpart_p and
00569   // at least some compilers won't call the destructor in this case.
00570   delete d->m_jsedlg;
00571   d->m_jsedlg = 0;
00572 
00573   if (!parentPart()) // only delete d->m_frame if the top khtml_part closes
00574       delete d->m_frame;
00575   else if (d->m_frame && d->m_frame->m_run) // for kids, they may get detached while
00576       d->m_frame->m_run.data()->abort();  //  resolving mimetype; cancel that if needed
00577   delete d; d = 0;
00578   KHTMLGlobal::deregisterPart( this );
00579 }
00580 
00581 bool KHTMLPart::restoreURL( const KUrl &url )
00582 {
00583   kDebug( 6050 ) << url;
00584 
00585   d->m_redirectionTimer.stop();
00586 
00587   /*
00588    * That's not a good idea as it will call closeUrl() on all
00589    * child frames, preventing them from further loading. This
00590    * method gets called from restoreState() in case of a full frameset
00591    * restoral, and restoreState() calls closeUrl() before restoring
00592    * anyway.
00593   kDebug( 6050 ) << "closing old URL";
00594   closeUrl();
00595   */
00596 
00597   d->m_bComplete = false;
00598   d->m_bLoadEventEmitted = false;
00599   d->m_workingURL = url;
00600 
00601   // set the java(script) flags according to the current host.
00602   d->m_bJScriptEnabled = KHTMLGlobal::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
00603   setDebugScript( KHTMLGlobal::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
00604   d->m_bJavaEnabled = KHTMLGlobal::defaultHTMLSettings()->isJavaEnabled(url.host());
00605   d->m_bPluginsEnabled = KHTMLGlobal::defaultHTMLSettings()->isPluginsEnabled(url.host());
00606 
00607   setUrl(url);
00608 
00609   d->m_restoreScrollPosition = true;
00610   disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
00611   connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
00612 
00613   KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
00614 
00615   emit started( 0L );
00616 
00617   return true;
00618 }
00619 
00620 bool KHTMLPartPrivate::isLocalAnchorJump( const KUrl& url )
00621 {
00622     // kio_help actually uses fragments to identify different pages, so
00623     // always reload with it.
00624     if (url.protocol() == QLatin1String("help"))
00625         return false;
00626 
00627     return url.hasRef() && url.equals( q->url(),
00628               KUrl::CompareWithoutTrailingSlash | KUrl::CompareWithoutFragment | KUrl::AllowEmptyPath );
00629 }
00630 
00631 void KHTMLPartPrivate::executeAnchorJump( const KUrl& url, bool lockHistory )
00632 {
00633     // Note: we want to emit openUrlNotify first thing, to make the history capture the old state.
00634     if (!lockHistory)
00635         emit m_extension->openUrlNotify();
00636 
00637     if ( !q->gotoAnchor( url.encodedHtmlRef()) )
00638         q->gotoAnchor( url.htmlRef() );
00639 
00640     q->setUrl(url);
00641     emit m_extension->setLocationBarUrl( url.prettyUrl() );
00642 }
00643 
00644 bool KHTMLPart::openUrl( const KUrl &url )
00645 {
00646   kDebug( 6050 ) << this << "opening" << url;
00647 
00648   // Wallet forms are per page, so clear it when loading a different page if we
00649   // are not an iframe (because we store walletforms only on the topmost part).
00650   if(!parentPart())
00651     d->m_walletForms.clear();
00652 
00653   d->m_redirectionTimer.stop();
00654 
00655   // check to see if this is an "error://" URL. This is caused when an error
00656   // occurs before this part was loaded (e.g. KonqRun), and is passed to
00657   // khtmlpart so that it can display the error.
00658   if ( url.protocol() == "error" ) {
00659     closeUrl();
00660 
00661     if(  d->m_bJScriptEnabled ) {
00662       d->m_statusBarText[BarOverrideText].clear();
00663       d->m_statusBarText[BarDefaultText].clear();
00664     }
00665 
00671     KUrl::List urls = KUrl::split( url );
00672     //kDebug(6050) << "Handling error URL. URL count:" << urls.count();
00673 
00674     if ( !urls.isEmpty() ) {
00675       const KUrl mainURL = urls.first();
00676       int error = mainURL.queryItem( "error" ).toInt();
00677       // error=0 isn't a valid error code, so 0 means it's missing from the URL
00678       if ( error == 0 ) error = KIO::ERR_UNKNOWN;
00679       const QString errorText = mainURL.queryItem( "errText" );
00680       urls.pop_front();
00681       d->m_workingURL = KUrl::join( urls );
00682       //kDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyUrl();
00683       emit d->m_extension->setLocationBarUrl( d->m_workingURL.prettyUrl() );
00684       htmlError( error, errorText, d->m_workingURL );
00685       return true;
00686     }
00687   }
00688 
00689   if (!parentPart()) { // only do it for toplevel part
00690     QString host = url.isLocalFile() ? "localhost" : url.host();
00691     QString userAgent = KProtocolManager::userAgentForHost(host);
00692     if (userAgent != KProtocolManager::userAgentForHost(QString())) {
00693       if (!d->m_statusBarUALabel) {
00694         d->m_statusBarUALabel = new KUrlLabel(d->m_statusBarExtension->statusBar());
00695         d->m_statusBarUALabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
00696         d->m_statusBarUALabel->setUseCursor(false);
00697         d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false);
00698         d->m_statusBarUALabel->setPixmap(SmallIcon("preferences-web-browser-identification"));
00699       }
00700       d->m_statusBarUALabel->setToolTip(i18n("The fake user-agent '%1' is in use.", userAgent));
00701     } else if (d->m_statusBarUALabel) {
00702       d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarUALabel);
00703       delete d->m_statusBarUALabel;
00704       d->m_statusBarUALabel = 0L;
00705     }
00706   }
00707 
00708   KParts::BrowserArguments browserArgs( d->m_extension->browserArguments() );
00709   KParts::OpenUrlArguments args( arguments() );
00710 
00711   // in case
00712   // a) we have no frameset (don't test m_frames.count(), iframes get in there)
00713   // b) the url is identical with the currently displayed one (except for the htmlref!)
00714   // c) the url request is not a POST operation and
00715   // d) the caller did not request to reload the page
00716   // e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi)
00717   // => we don't reload the whole document and
00718   // we just jump to the requested html anchor
00719   bool isFrameSet = false;
00720   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
00721       HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
00722       isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
00723   }
00724 
00725   if (isFrameSet && d->isLocalAnchorJump(url) && browserArgs.softReload)
00726   {
00727     QList<khtml::ChildFrame*>::Iterator it = d->m_frames.begin();
00728     const QList<khtml::ChildFrame*>::Iterator end = d->m_frames.end();
00729     for (; it != end; ++it) {
00730       KHTMLPart* const part = qobject_cast<KHTMLPart *>( (*it)->m_part.data() );
00731       if (part)
00732       {
00733         // We are reloading frames to make them jump into offsets.
00734         KParts::OpenUrlArguments partargs( part->arguments() );
00735         partargs.setReload( true );
00736         part->setArguments( partargs );
00737 
00738         part->openUrl( part->url() );
00739       }
00740     }/*next it*/
00741     return true;
00742   }
00743 
00744   if ( url.hasRef() && !isFrameSet )
00745   {
00746     bool noReloadForced = !args.reload() && !browserArgs.redirectedRequest() && !browserArgs.doPost();
00747     if ( noReloadForced &&  d->isLocalAnchorJump(url) )
00748     {
00749         kDebug( 6050 ) << "jumping to anchor. m_url = " << url;
00750         setUrl(url);
00751         emit started( 0 );
00752 
00753         if ( !gotoAnchor( url.encodedHtmlRef()) )
00754           gotoAnchor( url.htmlRef() );
00755 
00756         d->m_bComplete = true;
00757         if (d->m_doc)
00758             d->m_doc->setParsing(false);
00759 
00760         kDebug( 6050 ) << "completed...";
00761         emit completed();
00762         return true;
00763     }
00764   }
00765 
00766   // Save offset of viewport when page is reloaded to be compliant
00767   // to every other capable browser out there.
00768   if (args.reload()) {
00769     args.setXOffset( d->m_view->contentsX() );
00770     args.setYOffset( d->m_view->contentsY() );
00771     setArguments(args);
00772   }
00773 
00774   if (!d->m_restored)
00775     closeUrl();
00776 
00777   d->m_restoreScrollPosition = d->m_restored;
00778   disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
00779   connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
00780 
00781   // Classify the mimetype. Some, like images and plugins are handled
00782   // by wrapping things up in tags, so we want to plain output the HTML,
00783   // and not start the job and all that (since we would want the
00784   // KPart or whatever to load it).
00785   // This is also the only place we need to do this, as it's for
00786   // internal iframe use, not any other clients.
00787   MimeType type = d->classifyMimeType(args.mimeType());
00788 
00789   if (type == MimeImage || type == MimeOther) {
00790       begin(url, args.xOffset(), args.yOffset());
00791       write(QString::fromLatin1("<html><head></head><body>"));
00792       if (type == MimeImage)
00793           write(QString::fromLatin1("<img "));
00794       else
00795           write(QString::fromLatin1("<embed "));
00796       write(QString::fromLatin1("src=\""));
00797 
00798       assert(url.url().indexOf('"') == -1);
00799       write(url.url());
00800 
00801       write(QString::fromLatin1("\">"));
00802       end();
00803       return true;
00804   }
00805 
00806 
00807   // initializing m_url to the new url breaks relative links when opening such a link after this call and _before_ begin() is called (when the first
00808   // data arrives) (Simon)
00809   d->m_workingURL = url;
00810   if(url.protocol().startsWith( "http" ) && !url.host().isEmpty() &&
00811      url.path().isEmpty()) {
00812     d->m_workingURL.setPath("/");
00813     emit d->m_extension->setLocationBarUrl( d->m_workingURL.prettyUrl() );
00814   }
00815   setUrl(d->m_workingURL);
00816 
00817   QMap<QString,QString>& metaData = args.metaData();
00818   metaData.insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
00819   metaData.insert("ssl_parent_ip", d->m_ssl_parent_ip);
00820   metaData.insert("ssl_parent_cert", d->m_ssl_parent_cert);
00821   metaData.insert("PropagateHttpHeader", "true");
00822   metaData.insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
00823   metaData.insert("ssl_activate_warnings", "TRUE" );
00824   metaData.insert("cross-domain", toplevelURL().url());
00825 
00826   if (d->m_restored)
00827   {
00828      metaData.insert("referrer", d->m_pageReferrer);
00829      d->m_cachePolicy = KIO::CC_Cache;
00830   }
00831   else if (args.reload() && !browserArgs.softReload)
00832      d->m_cachePolicy = KIO::CC_Reload;
00833   else
00834      d->m_cachePolicy = KProtocolManager::cacheControl();
00835 
00836   if ( browserArgs.doPost() && (url.protocol().startsWith("http")) )
00837   {
00838       d->m_job = KIO::http_post( url, browserArgs.postData, KIO::HideProgressInfo );
00839       d->m_job->addMetaData("content-type", browserArgs.contentType() );
00840   }
00841   else
00842   {
00843       d->m_job = KIO::get( url, KIO::NoReload, KIO::HideProgressInfo );
00844       d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
00845   }
00846 
00847   if (widget())
00848      d->m_job->ui()->setWindow(widget()->topLevelWidget());
00849   d->m_job->addMetaData(metaData);
00850 
00851   connect( d->m_job, SIGNAL( result( KJob* ) ),
00852            SLOT( slotFinished( KJob* ) ) );
00853   connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
00854            SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
00855   connect ( d->m_job, SIGNAL( infoMessage( KJob*, const QString&, const QString& ) ),
00856            SLOT( slotInfoMessage(KJob*, const QString& ) ) );
00857   connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KUrl& ) ),
00858            SLOT( slotRedirection(KIO::Job*, const KUrl&) ) );
00859 
00860   d->m_bComplete = false;
00861   d->m_bLoadEventEmitted = false;
00862 
00863   // delete old status bar msg's from kjs (if it _was_ activated on last URL)
00864   if( d->m_bJScriptEnabled ) {
00865     d->m_statusBarText[BarOverrideText].clear();
00866     d->m_statusBarText[BarDefaultText].clear();
00867   }
00868 
00869   // set the javascript flags according to the current url
00870   d->m_bJScriptEnabled = KHTMLGlobal::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
00871   setDebugScript( KHTMLGlobal::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
00872   d->m_bJavaEnabled = KHTMLGlobal::defaultHTMLSettings()->isJavaEnabled(url.host());
00873   d->m_bPluginsEnabled = KHTMLGlobal::defaultHTMLSettings()->isPluginsEnabled(url.host());
00874 
00875 
00876   connect( d->m_job, SIGNAL( speed( KJob*, unsigned long ) ),
00877            this, SLOT( slotJobSpeed( KJob*, unsigned long ) ) );
00878 
00879   connect( d->m_job, SIGNAL( percent( KJob*, unsigned long ) ),
00880            this, SLOT( slotJobPercent( KJob*, unsigned long ) ) );
00881 
00882   connect( d->m_job, SIGNAL( result( KJob* ) ),
00883            this, SLOT( slotJobDone( KJob* ) ) );
00884 
00885   d->m_jobspeed = 0;
00886 
00887   // If this was an explicit reload and the user style sheet should be used,
00888   // do a stat to see whether the stylesheet was changed in the meanwhile.
00889   if ( args.reload() && !settings()->userStyleSheet().isEmpty() ) {
00890     KUrl url( settings()->userStyleSheet() );
00891     KIO::StatJob *job = KIO::stat( url, KIO::HideProgressInfo );
00892     connect( job, SIGNAL( result( KJob * ) ),
00893              this, SLOT( slotUserSheetStatDone( KJob * ) ) );
00894   }
00895   startingJob( d->m_job );
00896   emit started( 0L );
00897 
00898   return true;
00899 }
00900 
00901 bool KHTMLPart::closeUrl()
00902 {
00903   if ( d->m_job )
00904   {
00905     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
00906     d->m_job->kill();
00907     d->m_job = 0;
00908   }
00909 
00910   if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
00911     HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
00912 
00913     if ( hdoc->body() && d->m_bLoadEventEmitted ) {
00914       hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
00915       if ( d->m_doc )
00916         d->m_doc->updateRendering();
00917       d->m_bLoadEventEmitted = false;
00918     }
00919   }
00920 
00921   d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
00922   d->m_bLoadEventEmitted = true; // don't want that one either
00923   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
00924 
00925   disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
00926 
00927   KHTMLPageCache::self()->cancelFetch(this);
00928   if ( d->m_doc && d->m_doc->parsing() )
00929   {
00930     kDebug( 6050 ) << " was still parsing... calling end ";
00931     slotFinishedParsing();
00932     d->m_doc->setParsing(false);
00933   }
00934 
00935   if ( !d->m_workingURL.isEmpty() )
00936   {
00937     // Aborted before starting to render
00938     kDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << url().prettyUrl();
00939     emit d->m_extension->setLocationBarUrl( url().prettyUrl() );
00940   }
00941 
00942   d->m_workingURL = KUrl();
00943 
00944   if ( d->m_doc && d->m_doc->docLoader() )
00945     khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
00946 
00947   // tell all subframes to stop as well
00948   {
00949     ConstFrameIt it = d->m_frames.constBegin();
00950     const ConstFrameIt end = d->m_frames.constEnd();
00951     for (; it != end; ++it )
00952     {
00953       if ( (*it)->m_run )
00954         (*it)->m_run.data()->abort();
00955       if ( !( *it )->m_part.isNull() )
00956         ( *it )->m_part.data()->closeUrl();
00957     }
00958   }
00959   // tell all objects to stop as well
00960   {
00961     ConstFrameIt it = d->m_objects.constBegin();
00962     const ConstFrameIt end = d->m_objects.constEnd();
00963     for (; it != end; ++it)
00964     {
00965       if ( !( *it )->m_part.isNull() )
00966         ( *it )->m_part.data()->closeUrl();
00967     }
00968   }
00969   // Stop any started redirections as well!! (DA)
00970   if ( d && d->m_redirectionTimer.isActive() )
00971     d->m_redirectionTimer.stop();
00972 
00973   // null node activated.
00974   emit nodeActivated(Node());
00975 
00976   // make sure before clear() runs, we pop out of a dialog's message loop
00977   if ( d->m_view )
00978     d->m_view->closeChildDialogs();
00979 
00980   return true;
00981 }
00982 
00983 DOM::HTMLDocument KHTMLPart::htmlDocument() const
00984 {
00985   if (d->m_doc && d->m_doc->isHTMLDocument())
00986     return static_cast<HTMLDocumentImpl*>(d->m_doc);
00987   else
00988     return static_cast<HTMLDocumentImpl*>(0);
00989 }
00990 
00991 DOM::Document KHTMLPart::document() const
00992 {
00993     return d->m_doc;
00994 }
00995 
00996 QString KHTMLPart::documentSource() const
00997 {
00998   QString sourceStr;
00999   if ( !( url().isLocalFile() ) && KHTMLPageCache::self()->isComplete( d->m_cacheId ) )
01000   {
01001      QByteArray sourceArray;
01002      QDataStream dataStream( &sourceArray, QIODevice::WriteOnly );
01003      KHTMLPageCache::self()->saveData( d->m_cacheId, &dataStream );
01004      QTextStream stream( sourceArray, QIODevice::ReadOnly );
01005      stream.setCodec( QTextCodec::codecForName( encoding().toLatin1().constData() ) );
01006      sourceStr = stream.readAll();
01007   } else
01008   {
01009     QString tmpFile;
01010     if( KIO::NetAccess::download( url(), tmpFile, NULL ) )
01011     {
01012       QFile f( tmpFile );
01013       if ( f.open( QIODevice::ReadOnly ) )
01014       {
01015         QTextStream stream( &f );
01016         stream.setCodec( QTextCodec::codecForName( encoding().toLatin1().constData() ) );
01017         sourceStr = stream.readAll();
01018         f.close();
01019       }
01020       KIO::NetAccess::removeTempFile( tmpFile );
01021     }
01022   }
01023 
01024   return sourceStr;
01025 }
01026 
01027 
01028 KParts::BrowserExtension *KHTMLPart::browserExtension() const
01029 {
01030   return d->m_extension;
01031 }
01032 
01033 KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
01034 {
01035   return d->m_hostExtension;
01036 }
01037 
01038 KHTMLView *KHTMLPart::view() const
01039 {
01040   return d->m_view;
01041 }
01042 
01043 KHTMLViewBar *KHTMLPart::pTopViewBar() const
01044 {
01045   if (const_cast<KHTMLPart*>(this)->parentPart())
01046       return const_cast<KHTMLPart*>(this)->parentPart()->pTopViewBar();
01047   return d->m_topViewBar;
01048 }
01049 
01050 KHTMLViewBar *KHTMLPart::pBottomViewBar() const
01051 {
01052   if (const_cast<KHTMLPart*>(this)->parentPart())
01053       return const_cast<KHTMLPart*>(this)->parentPart()->pBottomViewBar();
01054   return d->m_bottomViewBar;
01055 }
01056 
01057 void KHTMLPart::setStatusMessagesEnabled( bool enable )
01058 {
01059   d->m_statusMessagesEnabled = enable;
01060 }
01061 
01062 KJS::Interpreter *KHTMLPart::jScriptInterpreter()
01063 {
01064   KJSProxy *proxy = jScript();
01065   if (!proxy || proxy->paused())
01066     return 0;
01067 
01068   return proxy->interpreter();
01069 }
01070 
01071 bool KHTMLPart::statusMessagesEnabled() const
01072 {
01073   return d->m_statusMessagesEnabled;
01074 }
01075 
01076 void KHTMLPart::setJScriptEnabled( bool enable )
01077 {
01078   if ( !enable && jScriptEnabled() && d->m_frame && d->m_frame->m_jscript ) {
01079     d->m_frame->m_jscript->clear();
01080   }
01081   d->m_bJScriptForce = enable;
01082   d->m_bJScriptOverride = true;
01083 }
01084 
01085 bool KHTMLPart::jScriptEnabled() const
01086 {
01087   if(onlyLocalReferences()) return false;
01088 
01089   if ( d->m_bJScriptOverride )
01090       return d->m_bJScriptForce;
01091   return d->m_bJScriptEnabled;
01092 }
01093 
01094 void KHTMLPart::setDNSPrefetch( DNSPrefetch pmode )
01095 {
01096   d->m_bDNSPrefetch = pmode;
01097   d->m_bDNSPrefetchIsDefault = false;
01098 }
01099 
01100 KHTMLPart::DNSPrefetch KHTMLPart::dnsPrefetch() const
01101 {
01102   if (onlyLocalReferences())
01103       return DNSPrefetchDisabled;
01104   return d->m_bDNSPrefetch;
01105 }
01106 
01107 void KHTMLPart::setMetaRefreshEnabled( bool enable )
01108 {
01109   d->m_metaRefreshEnabled = enable;
01110 }
01111 
01112 bool KHTMLPart::metaRefreshEnabled() const
01113 {
01114   return d->m_metaRefreshEnabled;
01115 }
01116 
01117 KJSProxy *KHTMLPart::jScript()
01118 {
01119   if (!jScriptEnabled()) return 0;
01120 
01121   if ( !d->m_frame ) {
01122       KHTMLPart * p = parentPart();
01123       if (!p) {
01124           d->m_frame = new khtml::ChildFrame;
01125           d->m_frame->m_part = this;
01126       } else {
01127           ConstFrameIt it = p->d->m_frames.constBegin();
01128           const ConstFrameIt end = p->d->m_frames.constEnd();
01129           for (; it != end; ++it)
01130               if ((*it)->m_part.data() == this) {
01131                   d->m_frame = *it;
01132                   break;
01133               }
01134       }
01135       if ( !d->m_frame )
01136         return 0;
01137   }
01138   if ( !d->m_frame->m_jscript )
01139      d->m_frame->m_jscript = new KJSProxy(d->m_frame);
01140   d->m_frame->m_jscript->setDebugEnabled(d->m_bJScriptDebugEnabled);
01141 
01142   return d->m_frame->m_jscript;
01143 }
01144 
01145 QVariant KHTMLPart::crossFrameExecuteScript(const QString& target,  const QString& script)
01146 {
01147   KHTMLPart* destpart = this;
01148 
01149   QString trg = target.toLower();
01150 
01151   if (target == "_top") {
01152     while (destpart->parentPart())
01153       destpart = destpart->parentPart();
01154   }
01155   else if (target == "_parent") {
01156     if (parentPart())
01157       destpart = parentPart();
01158   }
01159   else if (target == "_self" || target == "_blank")  {
01160     // we always allow these
01161   }
01162   else {
01163     destpart = findFrame(target);
01164     if (!destpart)
01165        destpart = this;
01166   }
01167 
01168   // easy way out?
01169   if (destpart == this)
01170     return executeScript(DOM::Node(), script);
01171 
01172   // now compare the domains
01173   if (destpart->checkFrameAccess(this))
01174     return destpart->executeScript(DOM::Node(), script);
01175 
01176   // eww, something went wrong. better execute it in our frame
01177   return executeScript(DOM::Node(), script);
01178 }
01179 
01180 //Enable this to see all JS scripts being executed
01181 //#define KJS_VERBOSE
01182 
01183 KJSErrorDlg *KHTMLPart::jsErrorExtension() {
01184   if (!d->m_settings->jsErrorsEnabled()) {
01185     return 0L;
01186   }
01187 
01188   if (parentPart()) {
01189     return parentPart()->jsErrorExtension();
01190   }
01191 
01192   if (!d->m_statusBarJSErrorLabel) {
01193     d->m_statusBarJSErrorLabel = new KUrlLabel(d->m_statusBarExtension->statusBar());
01194     d->m_statusBarJSErrorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
01195     d->m_statusBarJSErrorLabel->setUseCursor(false);
01196     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
01197     d->m_statusBarJSErrorLabel->setToolTip(i18n("This web page contains coding errors."));
01198     d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("script-error"));
01199     connect(d->m_statusBarJSErrorLabel, SIGNAL(leftClickedUrl()), SLOT(launchJSErrorDialog()));
01200     connect(d->m_statusBarJSErrorLabel, SIGNAL(rightClickedUrl()), SLOT(jsErrorDialogContextMenu()));
01201   }
01202   if (!d->m_jsedlg) {
01203     d->m_jsedlg = new KJSErrorDlg;
01204     d->m_jsedlg->setURL(url().prettyUrl());
01205     if (KGlobalSettings::showIconsOnPushButtons()) {
01206       d->m_jsedlg->_clear->setIcon(KIcon("edit-clear-locationbar-ltr"));
01207       d->m_jsedlg->_close->setIcon(KIcon("window-close"));
01208     }
01209   }
01210   return d->m_jsedlg;
01211 }
01212 
01213 void KHTMLPart::removeJSErrorExtension() {
01214   if (parentPart()) {
01215     parentPart()->removeJSErrorExtension();
01216     return;
01217   }
01218   if (d->m_statusBarJSErrorLabel != 0) {
01219     d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
01220     delete d->m_statusBarJSErrorLabel;
01221     d->m_statusBarJSErrorLabel = 0;
01222   }
01223   delete d->m_jsedlg;
01224   d->m_jsedlg = 0;
01225 }
01226 
01227 void KHTMLPart::disableJSErrorExtension() {
01228   removeJSErrorExtension();
01229   // These two lines are really kind of hacky, and it sucks to do this inside
01230   // KHTML but I don't know of anything that's reasonably easy as an alternative
01231   // right now.  It makes me wonder if there should be a more clean way to
01232   // contact all running "KHTML" instance as opposed to Konqueror instances too.
01233   d->m_settings->setJSErrorsEnabled(false);
01234   emit configurationChanged();
01235 }
01236 
01237 void KHTMLPart::jsErrorDialogContextMenu() {
01238   KMenu *m = new KMenu(0L);
01239   m->addAction(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
01240   m->addAction(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
01241   m->popup(QCursor::pos());
01242 }
01243 
01244 void KHTMLPart::launchJSErrorDialog() {
01245   KJSErrorDlg *dlg = jsErrorExtension();
01246   if (dlg) {
01247     dlg->show();
01248     dlg->raise();
01249   }
01250 }
01251 
01252 void KHTMLPart::launchJSConfigDialog() {
01253   QStringList args;
01254   args << "khtml_java_js";
01255   KToolInvocation::kdeinitExec( "kcmshell4", args );
01256 }
01257 
01258 QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script)
01259 {
01260 #ifdef KJS_VERBOSE
01261   // The script is now printed by KJS's Parser::parse
01262   kDebug(6070) << "executeScript: caller='" << objectName() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/;
01263 #endif
01264   KJSProxy *proxy = jScript();
01265 
01266   if (!proxy || proxy->paused())
01267     return QVariant();
01268 
01269   //Make sure to initialize the interpreter before creating Completion
01270   (void)proxy->interpreter();
01271 
01272   KJS::Completion comp;
01273 
01274   QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
01275 
01276   /*
01277    *  Error handling
01278    */
01279   if (comp.complType() == KJS::Throw && comp.value()) {
01280     KJSErrorDlg *dlg = jsErrorExtension();
01281     if (dlg) {
01282       QString msg = KJSDebugger::DebugWindow::exceptionToString(
01283                               proxy->interpreter()->globalExec(), comp.value());
01284       dlg->addError(i18n("<qt><b>Error</b>: %1: %2</qt>",
01285                          Qt::escape(filename), Qt::escape(msg)));
01286     }
01287   }
01288 
01289   // Handle immediate redirects now (e.g. location='foo')
01290   if ( !d->m_redirectURL.isEmpty() && d->m_delayRedirect == -1 )
01291   {
01292     kDebug(6070) << "executeScript done, handling immediate redirection NOW";
01293     // Must abort tokenizer, no further script must execute.
01294     khtml::Tokenizer* t = d->m_doc->tokenizer();
01295     if(t)
01296       t->abort();
01297     d->m_redirectionTimer.setSingleShot( true );
01298     d->m_redirectionTimer.start( 0 );
01299   }
01300 
01301   return ret;
01302 }
01303 
01304 QVariant KHTMLPart::executeScript( const QString &script )
01305 {
01306     return executeScript( DOM::Node(), script );
01307 }
01308 
01309 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
01310 {
01311 #ifdef KJS_VERBOSE
01312   kDebug(6070) << "caller=" << objectName() << "node=" << n.nodeName().string().toLatin1().constData() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */;
01313 #endif
01314   KJSProxy *proxy = jScript();
01315 
01316   if (!proxy || proxy->paused())
01317     return QVariant();
01318   (void)proxy->interpreter();//Make sure stuff is initialized
01319 
01320   ++(d->m_runningScripts);
01321   KJS::Completion comp;
01322   const QVariant ret = proxy->evaluate( QString(), 1, script, n, &comp );
01323   --(d->m_runningScripts);
01324 
01325   /*
01326    *  Error handling
01327    */
01328   if (comp.complType() == KJS::Throw && comp.value()) {
01329     KJSErrorDlg *dlg = jsErrorExtension();
01330     if (dlg) {
01331       QString msg = KJSDebugger::DebugWindow::exceptionToString(
01332                               proxy->interpreter()->globalExec(), comp.value());
01333       dlg->addError(i18n("<qt><b>Error</b>: node %1: %2</qt>",
01334                          n.nodeName().string(), Qt::escape(msg)));
01335     }
01336   }
01337 
01338   if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
01339       submitFormAgain();
01340 
01341 #ifdef KJS_VERBOSE
01342   kDebug(6070) << "done";
01343 #endif
01344   return ret;
01345 }
01346 
01347 void KHTMLPart::setJavaEnabled( bool enable )
01348 {
01349   d->m_bJavaForce = enable;
01350   d->m_bJavaOverride = true;
01351 }
01352 
01353 bool KHTMLPart::javaEnabled() const
01354 {
01355   if (onlyLocalReferences()) return false;
01356 
01357 #ifndef Q_WS_QWS
01358   if( d->m_bJavaOverride )
01359       return d->m_bJavaForce;
01360   return d->m_bJavaEnabled;
01361 #else
01362   return false;
01363 #endif
01364 }
01365 
01366 void KHTMLPart::setPluginsEnabled( bool enable )
01367 {
01368   d->m_bPluginsForce = enable;
01369   d->m_bPluginsOverride = true;
01370 }
01371 
01372 bool KHTMLPart::pluginsEnabled() const
01373 {
01374   if (onlyLocalReferences()) return false;
01375 
01376   if ( d->m_bPluginsOverride )
01377       return d->m_bPluginsForce;
01378   return d->m_bPluginsEnabled;
01379 }
01380 
01381 static int s_DOMTreeIndentLevel = 0;
01382 
01383 void KHTMLPart::slotDebugDOMTree()
01384 {
01385   if ( d->m_doc )
01386     qDebug("%s", d->m_doc->toString().string().toLatin1().constData());
01387 
01388   // Now print the contents of the frames that contain HTML
01389 
01390   const int indentLevel = s_DOMTreeIndentLevel++;
01391 
01392   ConstFrameIt it = d->m_frames.constBegin();
01393   const ConstFrameIt end = d->m_frames.constEnd();
01394   for (; it != end; ++it )
01395     if ( !( *it )->m_part.isNull() && (*it)->m_part.data()->inherits( "KHTMLPart" ) ) {
01396       KParts::ReadOnlyPart* const p = ( *it )->m_part.data();
01397       kDebug(6050) << QString().leftJustified(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->objectName() << " ";
01398       static_cast<KHTMLPart*>( p )->slotDebugDOMTree();
01399     }
01400   s_DOMTreeIndentLevel = indentLevel;
01401 }
01402 
01403 void KHTMLPart::slotDebugScript()
01404 {
01405   if (jScript())
01406     jScript()->showDebugWindow();
01407 }
01408 
01409 void KHTMLPart::slotDebugRenderTree()
01410 {
01411 #ifndef NDEBUG
01412   if ( d->m_doc ) {
01413     d->m_doc->renderer()->printTree();
01414     // dump out the contents of the rendering & DOM trees
01415 //    QString dumps;
01416 //    QTextStream outputStream(&dumps,QIODevice::WriteOnly);
01417 //    d->m_doc->renderer()->layer()->dump( outputStream );
01418 //    kDebug() << "dump output:" << "\n" + dumps;
01419 //    d->m_doc->renderer()->printLineBoxTree();
01420   }
01421 #endif
01422 }
01423 
01424 void KHTMLPart::slotDebugFrameTree()
01425 {
01426     khtml::ChildFrame::dumpFrameTree(this);
01427 }
01428 
01429 void KHTMLPart::slotStopAnimations()
01430 {
01431   stopAnimations();
01432 }
01433 
01434 void KHTMLPart::setAutoloadImages( bool enable )
01435 {
01436   if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
01437     return;
01438 
01439   if ( d->m_doc )
01440     d->m_doc->docLoader()->setAutoloadImages( enable );
01441 
01442   unplugActionList( "loadImages" );
01443 
01444   if ( enable ) {
01445     delete d->m_paLoadImages;
01446     d->m_paLoadImages = 0;
01447   }
01448   else if ( !d->m_paLoadImages ) {
01449     d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), this );
01450     actionCollection()->addAction( "loadImages", d->m_paLoadImages );
01451     d->m_paLoadImages->setIcon( KIcon( "image-loading" ) );
01452     connect( d->m_paLoadImages, SIGNAL( triggered( bool ) ), this, SLOT( slotLoadImages() ) );
01453   }
01454 
01455   if ( d->m_paLoadImages ) {
01456     QList<QAction*> lst;
01457     lst.append( d->m_paLoadImages );
01458     plugActionList( "loadImages", lst );
01459   }
01460 }
01461 
01462 bool KHTMLPart::autoloadImages() const
01463 {
01464   if ( d->m_doc )
01465     return d->m_doc->docLoader()->autoloadImages();
01466 
01467   return true;
01468 }
01469 
01470 void KHTMLPart::clear()
01471 {
01472   if ( d->m_bCleared )
01473     return;
01474 
01475   d->m_bCleared = true;
01476 
01477   d->m_bClearing = true;
01478 
01479   {
01480     ConstFrameIt it = d->m_frames.constBegin();
01481     const ConstFrameIt end = d->m_frames.constEnd();
01482     for(; it != end; ++it )
01483     {
01484       // Stop HTMLRun jobs for frames
01485       if ( (*it)->m_run )
01486         (*it)->m_run.data()->abort();
01487     }
01488   }
01489 
01490   {
01491     ConstFrameIt it = d->m_objects.constBegin();
01492     const ConstFrameIt end = d->m_objects.constEnd();
01493     for(; it != end; ++it )
01494     {
01495       // Stop HTMLRun jobs for objects
01496       if ( (*it)->m_run )
01497         (*it)->m_run.data()->abort();
01498     }
01499   }
01500 
01501 
01502   findTextBegin(); // resets d->m_findNode and d->m_findPos
01503   d->m_mousePressNode = DOM::Node();
01504 
01505 
01506   if ( d->m_doc )
01507   {
01508     if (d->m_doc->attached()) //the view may have detached it already
01509         d->m_doc->detach();
01510   }
01511 
01512   // Moving past doc so that onUnload works.
01513   if ( d->m_frame && d->m_frame->m_jscript )
01514     d->m_frame->m_jscript->clear();
01515 
01516   // stopping marquees
01517   if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
01518       d->m_doc->renderer()->layer()->suspendMarquees();
01519 
01520   if ( d->m_view )
01521     d->m_view->clear();
01522 
01523   // do not dereference the document before the jscript and view are cleared, as some destructors
01524   // might still try to access the document.
01525   if ( d->m_doc ) {
01526     d->m_doc->deref();
01527   }
01528   d->m_doc = 0;
01529 
01530   delete d->m_decoder;
01531   d->m_decoder = 0;
01532 
01533   // We don't want to change between parts if we are going to delete all of them anyway
01534   disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
01535                this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
01536 
01537   if (d->m_frames.count())
01538   {
01539     const KHTMLFrameList frames = d->m_frames;
01540     d->m_frames.clear();
01541     ConstFrameIt it = frames.begin();
01542     const ConstFrameIt end = frames.end();
01543     for(; it != end; ++it )
01544     {
01545       if ( (*it)->m_part )
01546       {
01547         partManager()->removePart( (*it)->m_part.data() );
01548         delete (*it)->m_part.data();
01549       }
01550       delete *it;
01551     }
01552   }
01553   d->m_suppressedPopupOriginParts.clear();
01554 
01555   if (d->m_objects.count())
01556   {
01557     KHTMLFrameList objects = d->m_objects;
01558     d->m_objects.clear();
01559     ConstFrameIt oi = objects.constBegin();
01560     const ConstFrameIt oiEnd = objects.constEnd();
01561 
01562     for (; oi != oiEnd; ++oi )
01563     {
01564       delete (*oi)->m_part.data();
01565       delete *oi;
01566     }
01567   }
01568 
01569   // Listen to part changes again
01570   connect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
01571              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
01572 
01573   d->clearRedirection();
01574   d->m_redirectLockHistory = true;
01575   d->m_bClearing = false;
01576   d->m_frameNameId = 1;
01577   d->m_bFirstData = true;
01578 
01579   d->m_bMousePressed = false;
01580 
01581   if (d->editor_context.m_caretBlinkTimer >= 0)
01582       killTimer(d->editor_context.m_caretBlinkTimer);
01583   d->editor_context.reset();
01584 #ifndef QT_NO_CLIPBOARD
01585   connect( qApp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
01586 #endif
01587 
01588   d->m_jobPercent = 0;
01589 
01590   if ( !d->m_haveEncoding )
01591     d->m_encoding.clear();
01592 
01593   d->m_DNSPrefetchQueue.clear();
01594   if (d->m_DNSPrefetchTimer > 0)
01595       killTimer(d->m_DNSPrefetchTimer);
01596   d->m_DNSPrefetchTimer = -1;
01597   d->m_lookedupHosts.clear();
01598   if (d->m_DNSTTLTimer > 0)
01599       killTimer(d->m_DNSTTLTimer);
01600   d->m_DNSTTLTimer = -1;
01601   d->m_numDNSPrefetchedNames = 0;
01602 
01603 #ifdef SPEED_DEBUG
01604   d->m_parsetime.restart();
01605 #endif
01606 }
01607 
01608 bool KHTMLPart::openFile()
01609 {
01610   return true;
01611 }
01612 
01613 DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
01614 {
01615     if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
01616         return static_cast<HTMLDocumentImpl*>(d->m_doc);
01617     return 0;
01618 }
01619 
01620 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
01621 {
01622     if ( d )
01623         return d->m_doc;
01624     return 0;
01625 }
01626 
01627 void KHTMLPart::slotInfoMessage(KJob* kio_job, const QString& msg)
01628 {
01629   assert(d->m_job == kio_job);
01630   Q_ASSERT(kio_job);
01631   Q_UNUSED(kio_job);
01632 
01633   if (!parentPart())
01634     setStatusBarText(msg, BarDefaultText);
01635 }
01636 
01637 void KHTMLPart::setPageSecurity( PageSecurity sec )
01638 {
01639   emit d->m_extension->setPageSecurity( sec );
01640 }
01641 
01642 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
01643 {
01644   assert ( d->m_job == kio_job );
01645   Q_ASSERT(kio_job);
01646   Q_UNUSED(kio_job);
01647 
01648   //kDebug( 6050 ) << "slotData: " << data.size();
01649   // The first data ?
01650   if ( !d->m_workingURL.isEmpty() )
01651   {
01652       //kDebug( 6050 ) << "begin!";
01653 
01654     // We must suspend KIO while we're inside begin() because it can cause
01655     // crashes if a window (such as kjsdebugger) goes back into the event loop,
01656     // more data arrives, and begin() gets called again (re-entered).
01657     d->m_job->suspend();
01658     begin( d->m_workingURL, arguments().xOffset(), arguments().yOffset() );
01659     d->m_job->resume();
01660 
01661     // CC_Refresh means : always send the server an If-Modified-Since conditional request.
01662     //                    This is the default cache setting and correspond to the KCM's "Keep cache in sync".
01663     // CC_Verify means :  only send a conditional request if the cache expiry date is passed.
01664     //                    It doesn't have a KCM setter.
01665     // We override the first to the second, except when doing a soft-reload.
01666     if (d->m_cachePolicy == KIO::CC_Refresh && !d->m_extension->browserArguments().softReload)
01667         d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify);
01668     else
01669         d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
01670 
01671     d->m_workingURL = KUrl();
01672 
01673     d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
01674 
01675     // When the first data arrives, the metadata has just been made available
01676     d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
01677     time_t cacheCreationDate =  d->m_job->queryMetaData("cache-creation-date").toLong();
01678     d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
01679 
01680     d->m_pageServices = d->m_job->queryMetaData("PageServices");
01681     d->m_pageReferrer = d->m_job->queryMetaData("referrer");
01682     d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
01683 
01684     {
01685     KHTMLPart *p = parentPart();
01686     if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
01687         while (p->parentPart()) p = p->parentPart();
01688 
01689         p->setPageSecurity( NotCrypted );
01690     }
01691     }
01692 
01693     setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
01694 
01695     // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
01696     d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
01697     d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
01698     d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
01699     d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
01700     d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
01701     d->m_ssl_protocol_version = d->m_job->queryMetaData("ssl_protocol_version");
01702     d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
01703     d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
01704     d->m_ssl_cert_errors = d->m_job->queryMetaData("ssl_cert_errors");
01705 
01706     // Check for charset meta-data
01707     QString qData = d->m_job->queryMetaData("charset");
01708     if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
01709        d->m_encoding = qData;
01710 
01711 
01712     // Support for http-refresh
01713     qData = d->m_job->queryMetaData("http-refresh");
01714     if( !qData.isEmpty())
01715       d->m_doc->processHttpEquiv("refresh", qData);
01716 
01717     // DISABLED: Support Content-Location per section 14.14 of RFC 2616.
01718     // See BR# 51185,BR# 82747
01719     /*
01720     QString baseURL = d->m_job->queryMetaData ("content-location");
01721     if (!baseURL.isEmpty())
01722       d->m_doc->setBaseURL(KUrl( d->m_doc->completeURL(baseURL) ));
01723     */
01724 
01725     // Support for Content-Language
01726     QString language = d->m_job->queryMetaData("content-language");
01727     if (!language.isEmpty())
01728       d->m_doc->setContentLanguage(language);
01729 
01730     if ( !url().isLocalFile() )
01731     {
01732       // Support for http last-modified
01733       d->m_lastModified = d->m_job->queryMetaData("modified");
01734     }
01735     else
01736       d->m_lastModified.clear(); // done on-demand by lastModified()
01737   }
01738 
01739   KHTMLPageCache::self()->addData(d->m_cacheId, data);
01740   write( data.data(), data.size() );
01741 }
01742 
01743 void KHTMLPart::slotRestoreData(const QByteArray &data )
01744 {
01745   // The first data ?
01746   if ( !d->m_workingURL.isEmpty() )
01747   {
01748      long saveCacheId = d->m_cacheId;
01749      QString savePageReferrer = d->m_pageReferrer;
01750      QString saveEncoding     = d->m_encoding;
01751      begin( d->m_workingURL, arguments().xOffset(), arguments().yOffset() );
01752      d->m_encoding     = saveEncoding;
01753      d->m_pageReferrer = savePageReferrer;
01754      d->m_cacheId = saveCacheId;
01755      d->m_workingURL = KUrl();
01756   }
01757 
01758   //kDebug( 6050 ) << data.size();
01759   write( data.data(), data.size() );
01760 
01761   if (data.size() == 0)
01762   {
01763       //kDebug( 6050 ) << "<<end of data>>";
01764      // End of data.
01765     if (d->m_doc && d->m_doc->parsing())
01766         end(); //will emit completed()
01767   }
01768 }
01769 
01770 void KHTMLPart::showError( KJob* job )
01771 {
01772   kDebug(6050) << "d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
01773                 << " d->m_bCleared=" << d->m_bCleared;
01774 
01775   if (job->error() == KIO::ERR_NO_CONTENT)
01776         return;
01777 
01778   if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
01779     job->uiDelegate()->showErrorMessage();
01780   else
01781   {
01782     htmlError( job->error(), job->errorText(), d->m_workingURL );
01783   }
01784 }
01785 
01786 // This is a protected method, placed here because of it's relevance to showError
01787 void KHTMLPart::htmlError( int errorCode, const QString& text, const KUrl& reqUrl )
01788 {
01789   kDebug(6050) << "errorCode" << errorCode << "text" << text;
01790   // make sure we're not executing any embedded JS
01791   bool bJSFO = d->m_bJScriptForce;
01792   bool bJSOO = d->m_bJScriptOverride;
01793   d->m_bJScriptForce = false;
01794   d->m_bJScriptOverride = true;
01795   begin();
01796 
01797   QString errorName, techName, description;
01798   QStringList causes, solutions;
01799 
01800   QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
01801   QDataStream stream(raw);
01802 
01803   stream >> errorName >> techName >> description >> causes >> solutions;
01804 
01805   QString url, protocol, datetime;
01806 
01807   // This is somewhat confusing, but we have to escape the externally-
01808   // controlled URL twice: once for i18n, and once for HTML.
01809   url = Qt::escape( Qt::escape( reqUrl.prettyUrl() ) );
01810   protocol = reqUrl.protocol();
01811   datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
01812                                                 KLocale::LongDate );
01813 
01814   QString filename( KStandardDirs::locate( "data", "khtml/error.html" ) );
01815   QFile file( filename );
01816   bool isOpened = file.open( QIODevice::ReadOnly );
01817   if ( !isOpened )
01818     kWarning(6050) << "Could not open error html template:" << filename;
01819 
01820   QString html = QString( QLatin1String( file.readAll() ) );
01821 
01822   html.replace( QLatin1String( "TITLE" ), i18n( "Error: %1 - %2", errorName, url ) );
01823   html.replace( QLatin1String( "DIRECTION" ), QApplication::isRightToLeft() ? "rtl" : "ltr" );
01824   html.replace( QLatin1String( "ICON_PATH" ), KIconLoader::global()->iconPath( "dialog-warning", -KIconLoader::SizeHuge ) );
01825 
01826   QString doc = QLatin1String( "<h1>" );
01827   doc += i18n( "The requested operation could not be completed" );
01828   doc += QLatin1String( "</h1><h2>" );
01829   doc += errorName;
01830   doc += QLatin1String( "</h2>" );
01831   if ( !techName.isNull() ) {
01832     doc += QLatin1String( "<h2>" );
01833     doc += i18n( "Technical Reason: " );
01834     doc += techName;
01835     doc += QLatin1String( "</h2>" );
01836   }
01837   doc += QLatin1String( "<br clear=\"all\">" );
01838   doc += QLatin1String( "<h3>" );
01839   doc += i18n( "Details of the Request:" );
01840   doc += QLatin1String( "</h3><ul><li>" );
01841   doc += i18n( "URL: %1" ,  url );
01842   doc += QLatin1String( "</li><li>" );
01843   if ( !protocol.isNull() ) {
01844     doc += i18n( "Protocol: %1", protocol );
01845     doc += QLatin1String( "</li><li>" );
01846   }
01847   doc += i18n( "Date and Time: %1" ,  datetime );
01848   doc += QLatin1String( "</li><li>" );
01849   doc += i18n( "Additional Information: %1" ,  text );
01850   doc += QLatin1String( "</li></ul><h3>" );
01851   doc += i18n( "Description:" );
01852   doc += QLatin1String( "</h3><p>" );
01853   doc += description;
01854   doc += QLatin1String( "</p>" );
01855   if ( causes.count() ) {
01856     doc += QLatin1String( "<h3>" );
01857     doc += i18n( "Possible Causes:" );
01858     doc += QLatin1String( "</h3><ul><li>" );
01859     doc += causes.join( "</li><li>" );
01860     doc += QLatin1String( "</li></ul>" );
01861   }
01862   if ( solutions.count() ) {
01863     doc += QLatin1String( "<h3>" );
01864     doc += i18n( "Possible Solutions:" );
01865     doc += QLatin1String( "</h3><ul><li>" );
01866     doc += solutions.join( "</li><li>" );
01867     doc += QLatin1String( "</li></ul>" );
01868   }
01869 
01870   html.replace( QLatin1String("TEXT"), doc );
01871 
01872   write( html );
01873   end();
01874 
01875   d->m_bJScriptForce = bJSFO;
01876   d->m_bJScriptOverride = bJSOO;
01877 
01878   // make the working url the current url, so that reload works and
01879   // emit the progress signals to advance one step in the history
01880   // (so that 'back' works)
01881   setUrl(reqUrl); // same as d->m_workingURL
01882   d->m_workingURL = KUrl();
01883   emit started( 0 );
01884   emit completed();
01885 }
01886 
01887 void KHTMLPart::slotFinished( KJob * job )
01888 {
01889   d->m_job = 0L;
01890   d->m_jobspeed = 0L;
01891 
01892   if (job->error())
01893   {
01894     KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
01895 
01896     // The following catches errors that occur as a result of HTTP
01897     // to FTP redirections where the FTP URL is a directory. Since
01898     // KIO cannot change a redirection request from GET to LISTDIR,
01899     // we have to take care of it here once we know for sure it is
01900     // a directory...
01901     if (job->error() == KIO::ERR_IS_DIRECTORY)
01902     {
01903       emit canceled( job->errorString() );
01904       emit d->m_extension->openUrlRequest( d->m_workingURL );
01905     }
01906     else
01907     {
01908       emit canceled( job->errorString() );
01909       // TODO: what else ?
01910       checkCompleted();
01911       showError( job );
01912     }
01913 
01914     return;
01915   }
01916   KIO::TransferJob *tjob = ::qobject_cast<KIO::TransferJob*>(job);
01917   if (tjob && tjob->isErrorPage()) {
01918     HTMLPartContainerElementImpl *elt = d->m_frame ?
01919                                            d->m_frame->m_partContainerElement.data() : 0;
01920 
01921     if (!elt)
01922       return;
01923 
01924     elt->partLoadingErrorNotify();
01925     checkCompleted();
01926     if (d->m_bComplete) return;
01927   }
01928 
01929   //kDebug( 6050 ) << "slotFinished";
01930 
01931   KHTMLPageCache::self()->endData(d->m_cacheId);
01932 
01933   if ( d->m_doc && d->m_doc->docLoader()->expireDate() && url().protocol().toLower().startsWith("http"))
01934       KIO::http_update_cache(url(), false, d->m_doc->docLoader()->expireDate());
01935 
01936   d->m_workingURL = KUrl();
01937 
01938   if ( d->m_doc && d->m_doc->parsing())
01939     end(); //will emit completed()
01940 }
01941 
01942 MimeType KHTMLPartPrivate::classifyMimeType(const QString& mimeStr)
01943 {
01944   // See HTML5's "5.5.1 Navigating across documents" section.
01945   if (mimeStr == "application/xhtml+xml")
01946       return MimeXHTML;
01947   if (mimeStr == "image/svg+xml")
01948       return MimeSVG;
01949   if (mimeStr == "text/html" || mimeStr.isEmpty())
01950       return MimeHTML;
01951 
01952   KMimeType::Ptr mime = KMimeType::mimeType(mimeStr, KMimeType::ResolveAliases);
01953   if ((mime && mime->is("text/xml")) || mimeStr.endsWith("+xml"))
01954       return MimeXML;
01955 
01956   if (mime && mime->is("text/plain"))
01957       return MimeText;
01958 
01959   if (khtmlImLoad::ImageManager::loaderDatabase()->supportedMimeTypes().contains(mimeStr))
01960       return MimeImage;
01961 
01962   // Sometimes our subclasses like to handle custom mimetypes. In that case,
01963   // we want to handle them as HTML. We do that in the following cases:
01964   // 1) We're at top-level, so we were forced to open something
01965   // 2) We're an object --- this again means we were forced to open something,
01966   //    as an iframe-generating-an-embed case would have us as an iframe
01967   if (!q->parentPart() || (m_frame && m_frame->m_type == khtml::ChildFrame::Object))
01968       return MimeHTML;
01969 
01970   return MimeOther;
01971 }
01972 
01973 void KHTMLPart::begin( const KUrl &url, int xOffset, int yOffset )
01974 {
01975   if ( d->m_view->underMouse() )
01976     QToolTip::hideText();  // in case a previous tooltip is still shown
01977 
01978   // No need to show this for a new page until an error is triggered
01979   if (!parentPart()) {
01980     removeJSErrorExtension();
01981     setSuppressedPopupIndicator( false );
01982     d->m_openableSuppressedPopups = 0;
01983     foreach ( KHTMLPart* part, d->m_suppressedPopupOriginParts ) {
01984       if (part) {
01985         KJS::Window *w = KJS::Window::retrieveWindow( part );
01986         if (w)
01987           w->forgetSuppressedWindows();
01988       }
01989     }
01990   }
01991 
01992   d->m_bCleared = false;
01993   d->m_cacheId = 0;
01994   d->m_bComplete = false;
01995   d->m_bLoadEventEmitted = false;
01996   clear();
01997   d->m_bCleared = false;
01998 
01999   if(url.isValid()) {
02000       QString urlString = url.url();
02001       KHTMLGlobal::vLinks()->insert( urlString );
02002       QString urlString2 = url.prettyUrl();
02003       if ( urlString != urlString2 ) {
02004           KHTMLGlobal::vLinks()->insert( urlString2 );
02005       }
02006   }
02007 
02008   // ###
02009   //stopParser();
02010 
02011   KParts::OpenUrlArguments args = arguments();
02012   args.setXOffset(xOffset);
02013   args.setYOffset(yOffset);
02014   setArguments(args);
02015 
02016   d->m_pageReferrer.clear();
02017 
02018   KUrl ref(url);
02019   d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
02020 
02021   setUrl(url);
02022 
02023   // Note: by now, any special mimetype besides plaintext would have been
02024   // handled specially inside openURL, so we handle their cases the same
02025   // as HTML.
02026   MimeType type = d->classifyMimeType(args.mimeType());
02027   switch (type) {
02028   case MimeSVG:
02029       d->m_doc = DOMImplementationImpl::createSVGDocument( d->m_view );
02030       break;
02031   case MimeXML: // any XML derivative, except XHTML or SVG
02032       // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
02033      d->m_doc = DOMImplementationImpl::createXMLDocument( d->m_view );
02034      break;
02035   case MimeText:
02036      d->m_doc = new HTMLTextDocumentImpl( d->m_view );
02037      break;
02038   case MimeXHTML:
02039   case MimeHTML:
02040   default:
02041       d->m_doc = DOMImplementationImpl::createHTMLDocument( d->m_view );
02042       // HTML or XHTML? (#86446)
02043       static_cast<HTMLDocumentImpl *>(d->m_doc)->setHTMLRequested( type != MimeXHTML );
02044   }
02045 
02046   d->m_doc->ref();
02047   d->m_doc->setURL( url.url() );
02048   d->m_doc->open( );
02049   if (!d->m_doc->attached())
02050     d->m_doc->attach( );
02051   d->m_doc->setBaseURL( KUrl() );
02052   d->m_doc->docLoader()->setShowAnimations( KHTMLGlobal::defaultHTMLSettings()->showAnimations() );
02053   emit docCreated();
02054 
02055   d->m_paUseStylesheet->setItems(QStringList());
02056   d->m_paUseStylesheet->setEnabled( false );
02057 
02058   setAutoloadImages( KHTMLGlobal::defaultHTMLSettings()->autoLoadImages() );
02059   QString userStyleSheet = KHTMLGlobal::defaultHTMLSettings()->userStyleSheet();
02060   if ( !userStyleSheet.isEmpty() )
02061     setUserStyleSheet( KUrl( userStyleSheet ) );
02062 
02063   d->m_doc->setRestoreState(d->m_extension->browserArguments().docState);
02064   connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02065 
02066   emit d->m_extension->enableAction( "print", true );
02067 
02068   d->m_doc->setParsing(true);
02069 }
02070 
02071 void KHTMLPart::write( const char *data, int len )
02072 {
02073   if ( !d->m_decoder )
02074     d->m_decoder = createDecoder();
02075 
02076   if ( len == -1 )
02077     len = strlen( data );
02078 
02079   if ( len == 0 )
02080     return;
02081 
02082   QString decoded=d->m_decoder->decodeWithBuffering(data,len);
02083 
02084   if(decoded.isEmpty())
02085       return;
02086 
02087   if(d->m_bFirstData)
02088       onFirstData();
02089 
02090   khtml::Tokenizer* t = d->m_doc->tokenizer();
02091   if(t)
02092     t->write( decoded, true );
02093 }
02094 
02095 // ### KDE5: remove
02096 void KHTMLPart::setAlwaysHonourDoctype( bool b )
02097 {
02098     d->m_bStrictModeQuirk = !b;
02099 }
02100 
02101 void KHTMLPart::write( const QString &str )
02102 {
02103     if ( str.isNull() )
02104         return;
02105 
02106     if(d->m_bFirstData) {
02107             // determine the parse mode
02108         if (d->m_bStrictModeQuirk) {
02109             d->m_doc->setParseMode( DocumentImpl::Strict );
02110             d->m_bFirstData = false;
02111         } else {
02112             onFirstData();
02113         }
02114     }
02115     khtml::Tokenizer* t = d->m_doc->tokenizer();
02116     if(t)
02117         t->write( str, true );
02118 }
02119 
02120 void KHTMLPart::end()
02121 {
02122     if (d->m_doc) {
02123         if (d->m_decoder)
02124         {
02125             QString decoded=d->m_decoder->flush();
02126             if (d->m_bFirstData)
02127                 onFirstData();
02128             if (!decoded.isEmpty())
02129                 write(decoded);
02130         }
02131         d->m_doc->finishParsing();
02132     }
02133 }
02134 
02135 void KHTMLPart::onFirstData()
02136 {
02137       assert( d->m_bFirstData );
02138 
02139       // determine the parse mode
02140       d->m_doc->determineParseMode();
02141       d->m_bFirstData = false;
02142 
02143       // ### this is still quite hacky, but should work a lot better than the old solution
02144       // Note: decoder may be null if only write(QString) is used.
02145       if (d->m_decoder && d->m_decoder->visuallyOrdered())
02146           d->m_doc->setVisuallyOrdered();
02147       // ensure part and view shares zoom-level before styling
02148       updateZoomFactor();
02149       d->m_doc->recalcStyle( NodeImpl::Force );
02150 }
02151 
02152 bool KHTMLPart::doOpenStream( const QString& mimeType )
02153 {
02154     KMimeType::Ptr mime = KMimeType::mimeType(mimeType, KMimeType::ResolveAliases);
02155     if ( mime && ( mime->is( "text/html" ) || mime->is( "text/xml" ) ) )
02156     {
02157         begin( url() );
02158         return true;
02159     }
02160     return false;
02161 }
02162 
02163 bool KHTMLPart::doWriteStream( const QByteArray& data )
02164 {
02165     write( data.data(), data.size() );
02166     return true;
02167 }
02168 
02169 bool KHTMLPart::doCloseStream()
02170 {
02171     end();
02172     return true;
02173 }
02174 
02175 
02176 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
02177 {
02178     if (!d->m_view) return;
02179     d->m_view->paint(p, rc, yOff, more);
02180 }
02181 
02182 void KHTMLPart::stopAnimations()
02183 {
02184   if ( d->m_doc )
02185     d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
02186 
02187   ConstFrameIt it = d->m_frames.constBegin();
02188   const ConstFrameIt end = d->m_frames.constEnd();
02189   for (; it != end; ++it ) {
02190     if ( KHTMLPart* p = qobject_cast<KHTMLPart*>((*it)->m_part.data()) )
02191       p->stopAnimations();
02192   }
02193 }
02194 
02195 void KHTMLPart::resetFromScript()
02196 {
02197     closeUrl();
02198     d->m_bComplete = false;
02199     d->m_bLoadEventEmitted = false;
02200     disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02201     connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02202     d->m_doc->setParsing(true);
02203 
02204     emit started( 0L );
02205 }
02206 
02207 void KHTMLPart::slotFinishedParsing()
02208 {
02209   d->m_doc->setParsing(false);
02210   d->m_doc->dispatchHTMLEvent(EventImpl::KHTML_CONTENTLOADED_EVENT, true, false);
02211   checkEmitLoadEvent();
02212   disconnect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
02213 
02214   if (!d->m_view)
02215     return; // We are probably being destructed.
02216 
02217   checkCompleted();
02218 }
02219 
02220 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
02221 {
02222   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
02223     KHTMLPart* p = this;
02224     while ( p ) {
02225       KHTMLPart* const op = p;
02226       ++(p->d->m_totalObjectCount);
02227       p = p->parentPart();
02228       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount
02229         && !op->d->m_progressUpdateTimer.isActive()) {
02230         op->d->m_progressUpdateTimer.setSingleShot( true );
02231         op->d->m_progressUpdateTimer.start( 200 );
02232       }
02233     }
02234   }
02235 }
02236 
02237 static bool isAncestorOrSamePart(KHTMLPart* p1, KHTMLPart* p2)
02238 {
02239     KHTMLPart* p = p2;
02240     do {
02241         if (p == p1)
02242             return true;
02243     } while ((p = p->parentPart()));
02244     return false;
02245 }
02246 
02247 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
02248 {
02249   if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
02250     KHTMLPart* p = this;
02251     while ( p ) {
02252       KHTMLPart* const op = p;
02253       ++(p->d->m_loadedObjects);
02254       p = p->parentPart();
02255       if ( !p && op->d->m_loadedObjects <= op->d->m_totalObjectCount && op->d->m_jobPercent <= 100
02256         && !op->d->m_progressUpdateTimer.isActive()) {
02257         op->d->m_progressUpdateTimer.setSingleShot( true );
02258         op->d->m_progressUpdateTimer.start( 200 );
02259       }
02260     }
02261   }
02263   //  then our loading state can't possibly be affected : don't waste time checking for completion.
02264   if (!d->m_doc || !dl->doc()->part() || !isAncestorOrSamePart(this, dl->doc()->part()))
02265       return;
02266   checkCompleted();
02267 }
02268 
02269 void KHTMLPart::slotProgressUpdate()
02270 {
02271   int percent;
02272   if ( d->m_loadedObjects < d->m_totalObjectCount )
02273     percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
02274   else
02275     percent = d->m_jobPercent;
02276 
02277   if( d->m_bComplete )
02278     percent = 100;
02279 
02280   if (d->m_statusMessagesEnabled) {
02281     if( d->m_bComplete )
02282       emit d->m_extension->infoMessage( i18n( "Page loaded." ));
02283     else if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
02284       emit d->m_extension->infoMessage( i18np( "%1 Image of %2 loaded.", "%1 Images of %2 loaded.", d->m_loadedObjects, d->m_totalObjectCount) );
02285   }
02286 
02287   emit d->m_extension->loadingProgress( percent );
02288 }
02289 
02290 void KHTMLPart::slotJobSpeed( KJob* /*job*/, unsigned long speed )
02291 {
02292   d->m_jobspeed = speed;
02293   if (!parentPart())
02294     setStatusBarText(jsStatusBarText(), BarOverrideText);
02295 }
02296 
02297 void KHTMLPart::slotJobPercent( KJob* /*job*/, unsigned long percent )
02298 {
02299   d->m_jobPercent = percent;
02300 
02301   if ( !parentPart() ) {
02302     d->m_progressUpdateTimer.setSingleShot( true );
02303     d->m_progressUpdateTimer.start( 0 );
02304   }
02305 }
02306 
02307 void KHTMLPart::slotJobDone( KJob* /*job*/ )
02308 {
02309   d->m_jobPercent = 100;
02310 
02311   if ( !parentPart() ) {
02312     d->m_progressUpdateTimer.setSingleShot( true );
02313     d->m_progressUpdateTimer.start( 0 );
02314   }
02315 }
02316 
02317 void KHTMLPart::slotUserSheetStatDone( KJob *_job )
02318 {
02319   using namespace KIO;
02320 
02321   if ( _job->error() ) {
02322     showError( _job );
02323     return;
02324   }
02325 
02326   const UDSEntry entry = dynamic_cast<KIO::StatJob *>( _job )->statResult();
02327   const time_t lastModified = entry.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME, -1 );
02328 
02329   // If the filesystem supports modification times, only reload the
02330   // user-defined stylesheet if necessary - otherwise always reload.
02331   if ( lastModified != static_cast<time_t>(-1) ) {
02332     if ( d->m_userStyleSheetLastModified >= lastModified ) {
02333       return;
02334     }
02335     d->m_userStyleSheetLastModified = lastModified;
02336   }
02337 
02338   setUserStyleSheet( KUrl( settings()->userStyleSheet() ) );
02339 }
02340 
02341 bool KHTMLPartPrivate::isFullyLoaded(bool* pendingRedirections) const
02342 {
02343   *pendingRedirections = false;
02344 
02345   // Any frame that hasn't completed yet ?
02346   ConstFrameIt it = m_frames.constBegin();
02347   const ConstFrameIt end = m_frames.constEnd();
02348   for (; it != end; ++it ) {
02349     if ( !(*it)->m_bCompleted || (*it)->m_run )
02350     {
02351       //kDebug( 6050 ) << this << " is waiting for " << (*it)->m_part;
02352       return false;
02353     }
02354     // Check for frames with pending redirections
02355     if ( (*it)->m_bPendingRedirection )
02356       *pendingRedirections = true;
02357   }
02358 
02359   // Any object that hasn't completed yet ?
02360   {
02361     ConstFrameIt oi = m_objects.constBegin();
02362     const ConstFrameIt oiEnd = m_objects.constEnd();
02363 
02364     for (; oi != oiEnd; ++oi )
02365       if ( !(*oi)->m_bCompleted )
02366         return false;
02367   }
02368 
02369   // Are we still parsing
02370   if ( m_doc && m_doc->parsing() )
02371     return false;
02372 
02373   // Still waiting for images/scripts from the loader ?
02374   int requests = 0;
02375   if ( m_doc && m_doc->docLoader() )
02376     requests = khtml::Cache::loader()->numRequests( m_doc->docLoader() );
02377 
02378   if ( requests > 0 )
02379   {
02380     //kDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests;
02381     return false;
02382   }
02383 
02384   return true;
02385 }
02386 
02387 void KHTMLPart::checkCompleted()
02388 {
02389 //   kDebug( 6050 ) << this;
02390 //   kDebug( 6050 ) << "   parsing: " << (d->m_doc && d->m_doc->parsing());
02391 //   kDebug( 6050 ) << "   complete: " << d->m_bComplete;
02392 
02393   // restore the cursor position
02394   if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
02395   {
02396       if (d->m_focusNodeNumber >= 0)
02397           d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
02398 
02399       d->m_focusNodeRestored = true;
02400   }
02401 
02402   bool fullyLoaded, pendingChildRedirections;
02403   fullyLoaded = d->isFullyLoaded(&pendingChildRedirections);
02404 
02405   // Are we still loading, or already have done the relevant work?
02406   if (!fullyLoaded || d->m_bComplete)
02407     return;
02408 
02409   // OK, completed.
02410   // Now do what should be done when we are really completed.
02411   d->m_bComplete = true;
02412   d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
02413   d->m_totalObjectCount = 0;
02414   d->m_loadedObjects = 0;
02415 
02416   KHTMLPart* p = this;
02417   while ( p ) {
02418     KHTMLPart* op = p;
02419     p = p->parentPart();
02420     if ( !p && !op->d->m_progressUpdateTimer.isActive()) {
02421       op->d->m_progressUpdateTimer.setSingleShot( true );
02422       op->d->m_progressUpdateTimer.start( 0 );
02423     }
02424   }
02425 
02426   checkEmitLoadEvent(); // if we didn't do it before
02427 
02428   bool pendingAction = false;
02429 
02430   if ( !d->m_redirectURL.isEmpty() )
02431   {
02432     // DA: Do not start redirection for frames here! That action is
02433     // deferred until the parent emits a completed signal.
02434     if ( parentPart() == 0 ) {
02435       //kDebug(6050) << this << " starting redirection timer";
02436       d->m_redirectionTimer.setSingleShot( true );
02437       d->m_redirectionTimer.start( qMax(0, 1000 * d->m_delayRedirect) );
02438     } else {
02439       //kDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted.";
02440     }
02441 
02442     pendingAction = true;
02443   }
02444   else if ( pendingChildRedirections )
02445   {
02446     pendingAction = true;
02447   }
02448 
02449   // the view will emit completed on our behalf,
02450   // either now or at next repaint if one is pending
02451 
02452   //kDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction;
02453   d->m_view->complete( pendingAction );
02454 
02455   // find the alternate stylesheets
02456   QStringList sheets;
02457   if (d->m_doc)
02458      sheets = d->m_doc->availableStyleSheets();
02459   sheets.prepend( i18n( "Automatic Detection" ) );
02460   d->m_paUseStylesheet->setItems( sheets );
02461 
02462   d->m_paUseStylesheet->setEnabled( sheets.count() > 2);
02463   if (sheets.count() > 2)
02464   {
02465     d->m_paUseStylesheet->setCurrentItem(qMax(sheets.indexOf(d->m_sheetUsed), 0));
02466     slotUseStylesheet();
02467   }
02468 
02469   setJSDefaultStatusBarText(QString());
02470 
02471 #ifdef SPEED_DEBUG
02472   if (!parentPart())
02473       kDebug(6080) << "DONE:" <<d->m_parsetime.elapsed();
02474 #endif
02475 }
02476 
02477 void KHTMLPart::checkEmitLoadEvent()
02478 {
02479   bool fullyLoaded, pendingChildRedirections;
02480   fullyLoaded = d->isFullyLoaded(&pendingChildRedirections);
02481 
02482   // ### might want to wait on pendingChildRedirections here, too
02483   if ( d->m_bLoadEventEmitted || !d->m_doc || !fullyLoaded ) return;
02484 
02485   d->m_bLoadEventEmitted = true;
02486   if (d->m_doc)
02487     d->m_doc->close();
02488 }
02489 
02490 const KHTMLSettings *KHTMLPart::settings() const
02491 {
02492   return d->m_settings;
02493 }
02494 
02495 #ifndef KDE_NO_COMPAT // KDE5: remove this ifndef, keep the method (renamed to baseUrl)
02496 KUrl KHTMLPart::baseURL() const
02497 {
02498   if ( !d->m_doc ) return KUrl();
02499 
02500   return d->m_doc->baseURL();
02501 }
02502 #endif
02503 
02504 KUrl KHTMLPart::completeURL( const QString &url )
02505 {
02506   if ( !d->m_doc ) return KUrl( url );
02507 
02508 #if 0
02509   if (d->m_decoder)
02510     return KUrl(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
02511 #endif
02512 
02513   return KUrl( d->m_doc->completeURL( url ) );
02514 }
02515 
02516 QString KHTMLPartPrivate::codeForJavaScriptURL(const QString &u)
02517 {
02518     return KUrl::fromPercentEncoding( u.right( u.length() - 11 ).toUtf8() );
02519 }
02520 
02521 void KHTMLPartPrivate::executeJavascriptURL(const QString &u)
02522 {
02523     QString script = codeForJavaScriptURL(u);
02524     kDebug( 6050 ) << "script=" << script;
02525     QVariant res = q->executeScript( DOM::Node(), script );
02526     if ( res.type() == QVariant::String ) {
02527       q->begin( q->url() );
02528       q->setAlwaysHonourDoctype(); // Disable public API compat; it messes with doctype
02529       q->write( res.toString() );
02530       q->end();
02531     }
02532     emit q->completed();
02533 }
02534 
02535 bool KHTMLPartPrivate::isJavaScriptURL(const QString& url)
02536 {
02537     return url.indexOf( QLatin1String( "javascript:" ), 0, Qt::CaseInsensitive ) == 0;
02538 }
02539 
02540 // Called by ecma/kjs_window in case of redirections from Javascript,
02541 // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
02542 void KHTMLPart::scheduleRedirection( int delay, const QString &url, bool doLockHistory )
02543 {
02544   kDebug(6050) << "delay=" << delay << " url=" << url << " from=" << this->url() << "parent=" << parentPart();
02545   kDebug(6050) << "current redirectURL=" << d->m_redirectURL << " with delay " << d->m_delayRedirect;
02546 
02547   // In case of JS redirections, some, such as jump to anchors, and javascript:
02548   // evaluation should actually be handled immediately, and not waiting until
02549   // the end of the script. (Besides, we don't want to abort the tokenizer for those)
02550   if ( delay == -1 && d->isInPageURL(url) ) {
02551     d->executeInPageURL(url, doLockHistory);
02552     return;
02553   }
02554 
02555   if( delay < 24*60*60 &&
02556       ( d->m_redirectURL.isEmpty() || delay <= d->m_delayRedirect) ) {
02557     d->m_delayRedirect = delay;
02558     d->m_redirectURL = url;
02559     d->m_redirectLockHistory = doLockHistory;
02560     kDebug(6050) << " d->m_bComplete=" << d->m_bComplete;
02561 
02562     if ( d->m_bComplete ) {
02563       d->m_redirectionTimer.stop();
02564       d->m_redirectionTimer.setSingleShot( true );
02565       d->m_redirectionTimer.start( qMax(0, 1000 * d->m_delayRedirect) );
02566     }
02567   }
02568 }
02569 
02570 void KHTMLPartPrivate::clearRedirection()
02571 {
02572   m_delayRedirect = 0;
02573   m_redirectURL.clear();
02574   m_redirectionTimer.stop();
02575 }
02576 
02577 void KHTMLPart::slotRedirect()
02578 {
02579   kDebug(6050) << this;
02580   QString u = d->m_redirectURL;
02581   KUrl url( u );
02582   d->clearRedirection();
02583 
02584   if ( d->isInPageURL(u) )
02585   {
02586     d->executeInPageURL(u, d->m_redirectLockHistory);
02587     return;
02588   }
02589 
02590   KParts::OpenUrlArguments args;
02591   KUrl cUrl( this->url() );
02592 
02593   // handle windows opened by JS
02594   if ( openedByJS() && d->m_opener )
02595       cUrl = d->m_opener->url();
02596 
02597   if (!KAuthorized::authorizeUrlAction("redirect", cUrl, url))
02598   {
02599     kWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl << " to " << url << " REJECTED!";
02600     emit completed();
02601     return;
02602   }
02603 
02604   if ( url.equals(this->url(),
02605                 KUrl::CompareWithoutTrailingSlash | KUrl::CompareWithoutFragment | KUrl::AllowEmptyPath) )
02606   {
02607     args.metaData().insert("referrer", d->m_pageReferrer);
02608   }
02609 
02610   // For javascript and META-tag based redirections:
02611   //   - We don't take cross-domain-ness in consideration if we are the
02612   //   toplevel frame because the new URL may be in a different domain as the current URL
02613   //   but that's ok.
02614   //   - If we are not the toplevel frame then we check against the toplevelURL()
02615   if (parentPart())
02616       args.metaData().insert("cross-domain", toplevelURL().url());
02617 
02618   KParts::BrowserArguments browserArgs;
02619   browserArgs.setLockHistory( d->m_redirectLockHistory );
02620   // _self: make sure we don't use any <base target=>'s
02621 
02622   if ( !urlSelected( u, 0, 0, "_self", args, browserArgs ) ) {
02623     // urlSelected didn't open a url, so emit completed ourselves
02624     emit completed();
02625   }
02626 }
02627 
02628 void KHTMLPart::slotRedirection(KIO::Job*, const KUrl& url)
02629 {
02630   // the slave told us that we got redirected
02631   //kDebug( 6050 ) << "redirection by KIO to" << url;
02632   emit d->m_extension->setLocationBarUrl( url.prettyUrl() );
02633   d->m_workingURL = url;
02634 }
02635 
02636 bool KHTMLPart::setEncoding( const QString &name, bool override )
02637 {
02638     d->m_encoding = name;
02639     d->m_haveEncoding = override;
02640 
02641     if( !url().isEmpty() ) {
02642         // reload document
02643         closeUrl();
02644         KUrl oldUrl = url();
02645         setUrl(KUrl());
02646         d->m_restored = true;
02647         openUrl(oldUrl);
02648         d->m_restored = false;
02649     }
02650 
02651     return true;
02652 }
02653 
02654 QString KHTMLPart::encoding() const
02655 {
02656     if(d->m_haveEncoding && !d->m_encoding.isEmpty())
02657         return d->m_encoding;
02658 
02659     if(d->m_decoder && d->m_decoder->encoding())
02660         return QString(d->m_decoder->encoding());
02661 
02662     return defaultEncoding();
02663 }
02664 
02665 QString KHTMLPart::defaultEncoding() const
02666 {
02667   QString encoding = settings()->encoding();
02668   if ( !encoding.isEmpty() )
02669     return encoding;
02670   // HTTP requires the default encoding to be latin1, when neither
02671   // the user nor the page requested a particular encoding.
02672   if ( url().protocol().startsWith( "http" ) )
02673     return "iso-8859-1";
02674   else
02675     return KGlobal::locale()->encoding();
02676 }
02677 
02678 void KHTMLPart::setUserStyleSheet(const KUrl &url)
02679 {
02680   if ( d->m_doc && d->m_doc->docLoader() )
02681     (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
02682 }
02683 
02684 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
02685 {
02686   if ( d->m_doc )
02687     d->m_doc->setUserStyleSheet( styleSheet );
02688 }
02689 
02690 bool KHTMLPart::gotoAnchor( const QString &name )
02691 {
02692   if (!d->m_doc)
02693     return false;
02694 
02695   HTMLCollectionImpl *anchors =
02696       new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
02697   anchors->ref();
02698   NodeImpl *n = anchors->namedItem(name);
02699   anchors->deref();
02700 
02701   if(!n) {
02702       n = d->m_doc->getElementById( name );
02703   }
02704 
02705   d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
02706 
02707   // Implement the rule that "" and "top" both mean top of page as in other browsers.
02708   bool quirkyName = !n && !d->m_doc->inStrictMode() && (name.isEmpty() || name.toLower() == "top");
02709 
02710   if (quirkyName) {
02711       d->m_view->setContentsPos( d->m_view->contentsX(), 0);
02712       return true;
02713   } else if (!n) {
02714       kDebug(6050) << name << "not found";
02715       return false;
02716   }
02717 
02718   int x = 0, y = 0;
02719   int gox, dummy;
02720   HTMLElementImpl *a = static_cast<HTMLElementImpl *>(n);
02721 
02722   a->getUpperLeftCorner(x, y);
02723   if (x <= d->m_view->contentsX())
02724     gox = x - 10;
02725   else {
02726     gox = d->m_view->contentsX();
02727     if ( x + 10 > d->m_view->contentsX()+d->m_view->visibleWidth()) {
02728       a->getLowerRightCorner(x, dummy);
02729       gox = x - d->m_view->visibleWidth() + 10;
02730     }
02731   }
02732 
02733   d->m_view->setContentsPos(gox, y);
02734 
02735   return true;
02736 }
02737 
02738 bool KHTMLPart::nextAnchor()
02739 {
02740   if (!d->m_doc)
02741     return false;
02742   d->m_view->focusNextPrevNode ( true );
02743 
02744   return true;
02745 }
02746 
02747 bool KHTMLPart::prevAnchor()
02748 {
02749   if (!d->m_doc)
02750     return false;
02751   d->m_view->focusNextPrevNode ( false );
02752 
02753   return true;
02754 }
02755 
02756 void KHTMLPart::setStandardFont( const QString &name )
02757 {
02758     d->m_settings->setStdFontName(name);
02759 }
02760 
02761 void KHTMLPart::setFixedFont( const QString &name )
02762 {
02763     d->m_settings->setFixedFontName(name);
02764 }
02765 
02766 void KHTMLPart::setURLCursor( const QCursor &c )
02767 {
02768   d->m_linkCursor = c;
02769 }
02770 
02771 QCursor KHTMLPart::urlCursor() const
02772 {
02773   return d->m_linkCursor;
02774 }
02775 
02776 bool KHTMLPart::onlyLocalReferences() const
02777 {
02778   return d->m_onlyLocalReferences;
02779 }
02780 
02781 void KHTMLPart::setOnlyLocalReferences(bool enable)
02782 {
02783   d->m_onlyLocalReferences = enable;
02784 }
02785 
02786 bool KHTMLPart::forcePermitLocalImages() const
02787 {
02788     return d->m_forcePermitLocalImages;
02789 }
02790 
02791 void KHTMLPart::setForcePermitLocalImages(bool enable)
02792 {
02793     d->m_forcePermitLocalImages = enable;
02794 }
02795 
02796 void KHTMLPartPrivate::setFlagRecursively(
02797         bool KHTMLPartPrivate::*flag, bool value)
02798 {
02799   // first set it on the current one
02800   this->*flag = value;
02801 
02802   // descend into child frames recursively
02803   {
02804     QList<khtml::ChildFrame*>::Iterator it = m_frames.begin();
02805     const QList<khtml::ChildFrame*>::Iterator itEnd = m_frames.end();
02806     for (; it != itEnd; ++it) {
02807       KHTMLPart* const part = qobject_cast<KHTMLPart *>( (*it)->m_part.data() );
02808       if (part)
02809         part->d->setFlagRecursively(flag, value);
02810     }/*next it*/
02811   }
02812   // do the same again for objects
02813   {
02814     QList<khtml::ChildFrame*>::Iterator it = m_objects.begin();
02815     const QList<khtml::ChildFrame*>::Iterator itEnd = m_objects.end();
02816     for (; it != itEnd; ++it) {
02817       KHTMLPart* const part = qobject_cast<KHTMLPart *>( (*it)->m_part.data() );
02818       if (part)
02819         part->d->setFlagRecursively(flag, value);
02820     }/*next it*/
02821   }
02822 }
02823 
02824 void KHTMLPart::initCaret()
02825 {
02826   // initialize caret if not used yet
02827   if (d->editor_context.m_selection.state() == Selection::NONE) {
02828     if (d->m_doc) {
02829       NodeImpl *node;
02830       if (d->m_doc->isHTMLDocument()) {
02831         HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
02832         node = htmlDoc->body();
02833       } else
02834         node = d->m_doc;
02835       if (!node) return;
02836       d->editor_context.m_selection.moveTo(Position(node, 0));
02837       d->editor_context.m_selection.setNeedsLayout();
02838       d->editor_context.m_selection.needsCaretRepaint();
02839     }
02840   }
02841 }
02842 
02843 static void setCaretInvisibleIfNeeded(KHTMLPart *part)
02844 {
02845   // On contenteditable nodes, don't hide the caret
02846   if (!khtml::KHTMLPartAccessor::caret(part).caretPos().node()->isContentEditable())
02847     part->setCaretVisible(false);
02848 }
02849 
02850 void KHTMLPart::setCaretMode(bool enable)
02851 {
02852   kDebug(6200) << enable;
02853   if (isCaretMode() == enable) return;
02854   d->setFlagRecursively(&KHTMLPartPrivate::m_caretMode, enable);
02855   // FIXME: this won't work on frames as expected
02856   if (!isEditable()) {
02857     if (enable) {
02858       initCaret();
02859       setCaretVisible(true);
02860 //       view()->ensureCaretVisible();
02861     } else {
02862       setCaretInvisibleIfNeeded(this);
02863     }
02864   }
02865 }
02866 
02867 bool KHTMLPart::isCaretMode() const
02868 {
02869   return d->m_caretMode;
02870 }
02871 
02872 void KHTMLPart::setEditable(bool enable)
02873 {
02874   if (isEditable() == enable) return;
02875   d->setFlagRecursively(&KHTMLPartPrivate::m_designMode, enable);
02876   // FIXME: this won't work on frames as expected
02877   if (!isCaretMode()) {
02878     if (enable) {
02879       initCaret();
02880       setCaretVisible(true);
02881 //       view()->ensureCaretVisible();
02882     } else
02883       setCaretInvisibleIfNeeded(this);
02884   }
02885 }
02886 
02887 bool KHTMLPart::isEditable() const
02888 {
02889   return d->m_designMode;
02890 }
02891 
02892 khtml::EditorContext *KHTMLPart::editorContext() const {
02893     return &d->editor_context;
02894 }
02895 
02896 void KHTMLPart::setCaretPosition(DOM::Node node, long offset, bool extendSelection)
02897 {
02898   Q_UNUSED(node);
02899   Q_UNUSED(offset);
02900   Q_UNUSED(extendSelection);
02901 #ifndef KHTML_NO_CARET
02902 #if 0
02903   kDebug(6200) << "node: " << node.handle() << " nodeName: "
02904                << node.nodeName().string() << " offset: " << offset
02905                << " extendSelection " << extendSelection;
02906   if (view()->moveCaretTo(node.handle(), offset, !extendSelection))
02907     emitSelectionChanged();
02908   view()->ensureCaretVisible();
02909 #endif
02910 #endif // KHTML_NO_CARET
02911 }
02912 
02913 KHTMLPart::CaretDisplayPolicy KHTMLPart::caretDisplayPolicyNonFocused() const
02914 {
02915 #if 0
02916 #ifndef KHTML_NO_CARET
02917   return (CaretDisplayPolicy)view()->caretDisplayPolicyNonFocused();
02918 #else // KHTML_NO_CARET
02919   return CaretInvisible;
02920 #endif // KHTML_NO_CARET
02921 #endif
02922   return CaretInvisible;
02923 }
02924 
02925 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy)
02926 {
02927   Q_UNUSED(policy);
02928 #if 0
02929 #ifndef KHTML_NO_CARET
02930   view()->setCaretDisplayPolicyNonFocused(policy);
02931 #endif // KHTML_NO_CARET
02932 #endif
02933 }
02934 
02935 void KHTMLPart::setCaretVisible(bool show)
02936 {
02937   if (show) {
02938     NodeImpl *caretNode = d->editor_context.m_selection.caretPos().node();
02939     if (isCaretMode() || (caretNode && caretNode->isContentEditable())) {
02940         invalidateSelection();
02941         enableFindAheadActions(false);
02942     }
02943   } else {
02944 
02945     if (d->editor_context.m_caretBlinkTimer >= 0)
02946         killTimer(d->editor_context.m_caretBlinkTimer);
02947     clearCaretRectIfNeeded();
02948 
02949   }
02950 }
02951 
02952 void KHTMLPart::findTextBegin()
02953 {
02954   d->m_find.findTextBegin();
02955 }
02956 
02957 bool KHTMLPart::initFindNode( bool selection, bool reverse, bool fromCursor )
02958 {
02959   return d->m_find.initFindNode(selection, reverse, fromCursor);
02960 }
02961 
02962 void KHTMLPart::slotFind()
02963 {
02964   KParts::ReadOnlyPart *part = currentFrame();
02965   if (!part)
02966     return;
02967   if (!part->inherits("KHTMLPart") )
02968   {
02969       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
02970       return;
02971   }
02972   static_cast<KHTMLPart *>( part )->findText();
02973 }
02974 
02975 void KHTMLPart::slotFindNext()
02976 {
02977   KParts::ReadOnlyPart *part = currentFrame();
02978   if (!part)
02979     return;
02980   if (!part->inherits("KHTMLPart") )
02981   {
02982       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
02983       return;
02984   }
02985   static_cast<KHTMLPart *>( part )->findTextNext();
02986 }
02987 
02988 void KHTMLPart::slotFindPrev()
02989 {
02990   KParts::ReadOnlyPart *part = currentFrame();
02991   if (!part)
02992     return;
02993   if (!part->inherits("KHTMLPart") )
02994   {
02995       kError(6000) << "part is a" << part->metaObject()->className() << ", can't do a search into it";
02996       return;
02997   }
02998   static_cast<KHTMLPart *>( part )->findTextNext( true ); // reverse
02999 }
03000 
03001 void KHTMLPart::slotFindDone()
03002 {
03003   // ### remove me
03004 }
03005 
03006 void KHTMLPart::slotFindAheadText()
03007 {
03008   KHTMLPart *part = qobject_cast<KHTMLPart*>(currentFrame());
03009   if (!part)
03010     return;
03011   part->findText();
03012   KHTMLFindBar* findBar = part->d->m_find.findBar();
03013   findBar->setOptions(findBar->options() & ~FindLinksOnly);
03014 }
03015 
03016 void KHTMLPart::slotFindAheadLink()
03017 {
03018   KHTMLPart *part = qobject_cast<KHTMLPart*>(currentFrame());
03019   if (!part)
03020     return;
03021   part->findText();
03022   KHTMLFindBar* findBar = part->d->m_find.findBar();
03023   findBar->setOptions(findBar->options() | FindLinksOnly);
03024 }
03025 
03026 void KHTMLPart::enableFindAheadActions( bool )
03027 {
03028   // ### remove me
03029 }
03030 
03031 void KHTMLPart::slotFindDialogDestroyed()
03032 {
03033   // ### remove me
03034 }
03035 
03036 void KHTMLPart::findText()
03037 {
03038   if (parentPart())
03039       return parentPart()->findText();
03040   d->m_find.activate();
03041 }
03042 
03043 void KHTMLPart::findText( const QString &str, long options, QWidget *parent, KFindDialog *findDialog )
03044 {
03045   if (parentPart())
03046       return parentPart()->findText(str, options, parent, findDialog);
03047   d->m_find.createNewKFind(str, options, parent, findDialog );
03048 }
03049 
03050 // New method
03051 bool KHTMLPart::findTextNext( bool reverse )
03052 {
03053   if (parentPart())
03054       return parentPart()->findTextNext( reverse );
03055   return d->m_find.findTextNext( reverse );
03056 }
03057 
03058 bool KHTMLPart::pFindTextNextInThisFrame( bool reverse )
03059 {
03060   return d->m_find.findTextNext( reverse );
03061 }
03062 
03063 QString KHTMLPart::selectedTextAsHTML() const
03064 {
03065   const Selection &sel = d->editor_context.m_selection;
03066   if(!hasSelection()) {
03067     kDebug() << "Selection is not valid. Returning empty selection";
03068     return QString();
03069   }
03070   if(sel.start().offset() < 0 || sel.end().offset() < 0) {
03071     kDebug() << "invalid values for end/startOffset " << sel.start().offset() << " " << sel.end().offset();
03072     return QString();
03073   }
03074   DOM::Range r = selection();
03075   if(r.isNull() || r.isDetached())
03076     return QString();
03077   int exceptioncode = 0; //ignore the result
03078   return r.handle()->toHTML(exceptioncode).string();
03079 }
03080 
03081 QString KHTMLPart::selectedText() const
03082 {
03083   bool hasNewLine = true;
03084   bool seenTDTag = false;
03085   QString text;
03086   const Selection &sel = d->editor_context.m_selection;
03087   DOM::Node n = sel.start().node();
03088   while(!n.isNull()) {
03089       if(n.nodeType() == DOM::Node::TEXT_NODE && n.handle()->renderer()) {
03090         DOM::DOMStringImpl *dstr = static_cast<DOM::TextImpl*>(n.handle())->renderString();
03091         QString str(dstr->s, dstr->l);
03092         if(!str.isEmpty()) {
03093           if(seenTDTag) {
03094             text += "  ";
03095             seenTDTag = false;
03096           }
03097           hasNewLine = false;
03098           if(n == sel.start().node() && n == sel.end().node()) {
03099             int s = khtml::RenderPosition::fromDOMPosition(sel.start()).renderedOffset();
03100             int e = khtml::RenderPosition::fromDOMPosition(sel.end()).renderedOffset();
03101             text = str.mid(s, e-s);
03102           } else if(n == sel.start().node()) {
03103             text = str.mid(khtml::RenderPosition::fromDOMPosition(sel.start()).renderedOffset());
03104           } else if(n == sel.end().node()) {
03105             text += str.left(khtml::RenderPosition::fromDOMPosition(sel.end()).renderedOffset());
03106           } else
03107             text += str;
03108         }
03109       }
03110       else {
03111         // This is our simple HTML -> ASCII transformation:
03112         unsigned short id = n.elementId();
03113         switch(id) {
03114           case ID_TEXTAREA:
03115             text += static_cast<HTMLTextAreaElementImpl*>(n.handle())->value().string();
03116             break;
03117           case ID_INPUT:
03118             if (static_cast<HTMLInputElementImpl*>(n.handle())->inputType() != HTMLInputElementImpl::PASSWORD)
03119                 text += static_cast<HTMLInputElementImpl*>(n.handle())->value().string();
03120             break;
03121           case ID_SELECT:
03122             text += static_cast<HTMLSelectElementImpl*>(n.handle())->value().string();
03123             break;
03124           case ID_BR:
03125             text += "\n";
03126             hasNewLine = true;
03127             break;
03128           case ID_IMG:
03129             text += static_cast<HTMLImageElementImpl*>(n.handle())->altText().string();
03130             break;
03131           case ID_TD:
03132             break;
03133           case ID_TH:
03134           case ID_HR:
03135           case ID_OL:
03136           case ID_UL:
03137           case ID_LI:
03138           case ID_DD:
03139           case ID_DL:
03140           case ID_DT:
03141           case ID_PRE:
03142           case ID_LISTING:
03143           case ID_BLOCKQUOTE:
03144           case ID_DIV:
03145             if (!hasNewLine)
03146                text += "\n";
03147             hasNewLine = true;
03148             break;
03149           case ID_P:
03150           case ID_TR:
03151           case ID_H1:
03152           case ID_H2:
03153           case ID_H3:
03154           case ID_H4:
03155           case ID_H5:
03156           case ID_H6:
03157             if (!hasNewLine)
03158                text += "\n";
03159             hasNewLine = true;
03160             break;
03161         }
03162       }
03163       if(n == sel.end().node()) break;
03164       DOM::Node next = n.firstChild();
03165       if(next.isNull()) next = n.nextSibling();
03166       while( next.isNull() && !n.parentNode().isNull() ) {
03167         n = n.parentNode();
03168         next = n.nextSibling();
03169         unsigned short id = n.elementId();
03170         switch(id) {
03171           case ID_TD:
03172             seenTDTag = true; //Add two spaces after a td if then followed by text.
03173             break;
03174           case ID_TH:
03175           case ID_HR:
03176           case ID_OL:
03177           case ID_UL:
03178           case ID_LI:
03179           case ID_DD:
03180           case ID_DL:
03181           case ID_DT:
03182           case ID_PRE:
03183           case ID_LISTING:
03184           case ID_BLOCKQUOTE:
03185           case ID_DIV:
03186             seenTDTag = false;
03187             if (!hasNewLine)
03188                text += "\n";
03189             hasNewLine = true;
03190             break;
03191           case ID_P:
03192           case ID_TR:
03193           case ID_H1:
03194           case ID_H2:
03195           case ID_H3:
03196           case ID_H4:
03197           case ID_H5:
03198           case ID_H6:
03199             if (!hasNewLine)
03200                text += "\n";
03201 //            text += "\n";
03202             hasNewLine = true;
03203             break;
03204         }
03205       }
03206 
03207       n = next;
03208     }
03209 
03210     if(text.isEmpty())
03211         return QString();
03212 
03213     int start = 0;
03214     int end = text.length();
03215 
03216     // Strip leading LFs
03217     while ((start < end) && (text[start] == '\n'))
03218        ++start;
03219 
03220     // Strip excessive trailing LFs
03221     while ((start < (end-1)) && (text[end-1] == '\n') && (text[end-2] == '\n'))
03222        --end;
03223 
03224     return text.mid(start, end-start);
03225 }
03226 
03227 QString KHTMLPart::simplifiedSelectedText() const
03228 {
03229     QString text = selectedText();
03230     text.replace(QChar(0xa0), ' ');
03231     // remove leading and trailing whitespace
03232     while (!text.isEmpty() && text[0].isSpace())
03233         text = text.mid(1);
03234     while (!text.isEmpty() && text[text.length()-1].isSpace())
03235         text.truncate(text.length()-1);
03236     return text;
03237 }
03238 
03239 bool KHTMLPart::hasSelection() const
03240 {
03241     return !d->editor_context.m_selection.isEmpty() && !d->editor_context.m_selection.isCollapsed();
03242 }
03243 
03244 DOM::Range KHTMLPart::selection() const
03245 {
03246     return d->editor_context.m_selection.toRange();
03247 }
03248 
03249 void KHTMLPart::selection(DOM::Node &s, long &so, DOM::Node &e, long &eo) const
03250 {
03251     DOM::Range r = d->editor_context.m_selection.toRange();
03252     s = r.startContainer();
03253     so = r.startOffset();
03254     e = r.endContainer();
03255     eo = r.endOffset();
03256 }
03257 
03258 void KHTMLPart::setSelection( const DOM::Range &r )
03259 {
03260     setCaret(r);
03261 }
03262 
03263 const Selection &KHTMLPart::caret() const
03264 {
03265   return d->editor_context.m_selection;
03266 }
03267 
03268 const Selection &KHTMLPart::dragCaret() const
03269 {
03270   return d->editor_context.m_dragCaret;
03271 }
03272 
03273 void KHTMLPart::setCaret(const Selection &s, bool closeTyping)
03274 {
03275   if (d->editor_context.m_selection != s) {
03276     clearCaretRectIfNeeded();
03277     setFocusNodeIfNeeded(s);
03278     d->editor_context.m_selection = s;
03279     notifySelectionChanged(closeTyping);
03280   }
03281 }
03282 
03283 void KHTMLPart::setDragCaret(const DOM::Selection &dragCaret)
03284 {
03285   if (d->editor_context.m_dragCaret != dragCaret) {
03286     d->editor_context.m_dragCaret.needsCaretRepaint();
03287     d->editor_context.m_dragCaret = dragCaret;
03288     d->editor_context.m_dragCaret.needsCaretRepaint();
03289   }
03290 }
03291 
03292 void KHTMLPart::clearSelection()
03293 {
03294   clearCaretRectIfNeeded();
03295   setFocusNodeIfNeeded(d->editor_context.m_selection);
03296 #ifdef APPLE_CHANGES
03297   d->editor_context.m_selection.clear();
03298 #else
03299   d->editor_context.m_selection.collapse();
03300 #endif
03301   notifySelectionChanged();
03302 }
03303 
03304 void KHTMLPart::invalidateSelection()
03305 {
03306   clearCaretRectIfNeeded();
03307   d->editor_context.m_selection.setNeedsLayout();
03308   selectionLayoutChanged();
03309 }
03310 
03311 void KHTMLPart::setSelectionVisible(bool flag)
03312 {
03313   if (d->editor_context.m_caretVisible == flag)
03314     return;
03315 
03316   clearCaretRectIfNeeded();
03317   setFocusNodeIfNeeded(d->editor_context.m_selection);
03318   d->editor_context.m_caretVisible = flag;
03319 //   notifySelectionChanged();
03320 }
03321 
03322 #if 1
03323 void KHTMLPart::slotClearSelection()
03324 {
03325   if (!isCaretMode()
03326        && d->editor_context.m_selection.state() != Selection::NONE
03327        && !d->editor_context.m_selection.caretPos().node()->isContentEditable())
03328     clearCaretRectIfNeeded();
03329   bool hadSelection = hasSelection();
03330 #ifdef APPLE_CHANGES
03331   d->editor_context.m_selection.clear();
03332 #else
03333   d->editor_context.m_selection.collapse();
03334 #endif
03335   if (hadSelection)
03336     notifySelectionChanged();
03337 }
03338 #endif
03339 
03340 void KHTMLPart::clearCaretRectIfNeeded()
03341 {
03342   if (d->editor_context.m_caretPaint) {
03343     d->editor_context.m_caretPaint = false;
03344     d->editor_context.m_selection.needsCaretRepaint();
03345   }
03346 }
03347 
03348 void KHTMLPart::setFocusNodeIfNeeded(const Selection &s)
03349 {
03350   if (!xmlDocImpl() || s.state() == Selection::NONE)
03351     return;
03352 
03353   NodeImpl *n = s.start().node();
03354   NodeImpl *target = (n && n->isContentEditable()) ? n : 0;
03355   if (!target) {
03356     while (n && n != s.end().node()) {
03357       if (n->isContentEditable()) {
03358         target = n;
03359         break;
03360       }
03361       n = n->traverseNextNode();
03362     }
03363   }
03364   assert(target == 0 || target->isContentEditable());
03365 
03366   if (target) {
03367     for ( ; target && !target->isFocusable(); target = target->parentNode())
03368       {}
03369     if (target && target->isMouseFocusable())
03370       xmlDocImpl()->setFocusNode(target);
03371     else if (!target || !target->focused())
03372       xmlDocImpl()->setFocusNode(0);
03373   }
03374 }
03375 
03376 void KHTMLPart::selectionLayoutChanged()
03377 {
03378   // kill any caret blink timer now running
03379   if (d->editor_context.m_caretBlinkTimer >= 0) {
03380     killTimer(d->editor_context.m_caretBlinkTimer);
03381     d->editor_context.m_caretBlinkTimer = -1;
03382   }
03383 
03384   // see if a new caret blink timer needs to be started
03385   if (d->editor_context.m_caretVisible
03386       && d->editor_context.m_selection.state() != Selection::NONE) {
03387     d->editor_context.m_caretPaint = isCaretMode()
03388         || d->editor_context.m_selection.caretPos().node()->isContentEditable();
03389     if (d->editor_context.m_caretBlinks && d->editor_context.m_caretPaint)
03390       d->editor_context.m_caretBlinkTimer = startTimer(qApp->cursorFlashTime() / 2);
03391     d->editor_context.m_selection.needsCaretRepaint();
03392     // make sure that caret is visible
03393     QRect r(d->editor_context.m_selection.getRepaintRect());
03394     if (d->editor_context.m_caretPaint)
03395         d->m_view->ensureVisible(r.x(), r.y());
03396   }
03397 
03398   if (d->m_doc)
03399     d->m_doc->updateSelection();
03400 
03401   // Always clear the x position used for vertical arrow navigation.
03402   // It will be restored by the vertical arrow navigation code if necessary.
03403   d->editor_context.m_xPosForVerticalArrowNavigation = d->editor_context.NoXPosForVerticalArrowNavigation;
03404 }
03405 
03406 void KHTMLPart::notifySelectionChanged(bool closeTyping)
03407 {
03408   Editor *ed = d->editor_context.m_editor;
03409   selectionLayoutChanged();
03410   if (ed) {
03411     ed->clearTypingStyle();
03412 
03413     if (closeTyping)
03414         ed->closeTyping();
03415   }
03416 
03417   emitSelectionChanged();
03418 }
03419 
03420 void KHTMLPart::timerEvent(QTimerEvent *e)
03421 {
03422   if (e->timerId() == d->editor_context.m_caretBlinkTimer) {
03423     if (d->editor_context.m_caretBlinks &&
03424         d->editor_context.m_selection.state() != Selection::NONE) {
03425       d->editor_context.m_caretPaint = !d->editor_context.m_caretPaint;
03426       d->editor_context.m_selection.needsCaretRepaint();
03427     }
03428   } else if (e->timerId() == d->m_DNSPrefetchTimer) {
03429       // kDebug( 6050 ) << "will lookup " << d->m_DNSPrefetchQueue.head() << d->m_numDNSPrefetchedNames;
03430       KIO::HostInfo::prefetchHost( d->m_DNSPrefetchQueue.dequeue() );
03431       if (d->m_DNSPrefetchQueue.isEmpty()) {
03432           killTimer( d->m_DNSPrefetchTimer );
03433           d->m_DNSPrefetchTimer = -1;
03434       }
03435   } else if (e->timerId() == d->m_DNSTTLTimer) {
03436       foreach (const QString &name, d->m_lookedupHosts)
03437           d->m_DNSPrefetchQueue.enqueue(name);
03438       if (d->m_DNSPrefetchTimer <= 0)
03439          d->m_DNSPrefetchTimer = startTimer( sDNSPrefetchTimerDelay );
03440   }
03441 }
03442 
03443 bool KHTMLPart::mayPrefetchHostname( const QString& name )
03444 {
03445     if (d->m_bDNSPrefetch == DNSPrefetchDisabled)
03446         return false;
03447 
03448     if (d->m_numDNSPrefetchedNames >= sMaxDNSPrefetchPerPage)
03449         return false;
03450 
03451     if (d->m_bDNSPrefetch == DNSPrefetchOnlyWWWAndSLD) {
03452         int dots = name.count('.');
03453         if (dots > 2 || (dots == 2 &&  !name.startsWith("www.")))
03454             return false;
03455     }
03456 
03457     if ( d->m_lookedupHosts.contains( name ) )
03458         return false;
03459 
03460     d->m_DNSPrefetchQueue.enqueue( name );
03461     d->m_lookedupHosts.insert( name );
03462     d->m_numDNSPrefetchedNames++;
03463 
03464     if (d->m_DNSPrefetchTimer < 1)
03465         d->m_DNSPrefetchTimer = startTimer( sDNSPrefetchTimerDelay );
03466     if (d->m_DNSTTLTimer < 1)
03467         d->m_DNSTTLTimer = startTimer( sDNSTTLSeconds*1000 + 1 );
03468 
03469     return true;
03470 }
03471 
03472 void KHTMLPart::paintCaret(QPainter *p, const QRect &rect) const
03473 {
03474   if (d->editor_context.m_caretPaint)
03475     d->editor_context.m_selection.paintCaret(p, rect);
03476 }
03477 
03478 void KHTMLPart::paintDragCaret(QPainter *p, const QRect &rect) const
03479 {
03480   d->editor_context.m_dragCaret.paintCaret(p, rect);
03481 }
03482 
03483 DOM::Editor *KHTMLPart::editor() const {
03484   if (!d->editor_context.m_editor)
03485     const_cast<KHTMLPart *>(this)->d->editor_context.m_editor = new DOM::Editor(const_cast<KHTMLPart *>(this));
03486   return d->editor_context.m_editor;
03487 }
03488 
03489 void KHTMLPart::resetHoverText()
03490 {
03491    if( !d->m_overURL.isEmpty() ) // Only if we were showing a link
03492    {
03493      d->m_overURL.clear();
03494      d->m_overURLTarget.clear();
03495      emit onURL( QString() );
03496      // revert to default statusbar text
03497      setStatusBarText(QString(), BarHoverText);
03498      emit d->m_extension->mouseOverInfo(KFileItem());
03499   }
03500 }
03501 
03502 void KHTMLPart::overURL( const QString &url, const QString &target, bool /*shiftPressed*/ )
03503 {
03504   KUrl u = completeURL(url);
03505 
03506   // special case for <a href="">
03507   if ( url.isEmpty() )
03508     u.setFileName( url );
03509 
03510   emit onURL( url );
03511 
03512   if ( url.isEmpty() ) {
03513     setStatusBarText(Qt::escape(u.prettyUrl()), BarHoverText);
03514     return;
03515   }
03516 
03517   if ( d->isJavaScriptURL(url) ) {
03518     QString jscode = d->codeForJavaScriptURL( url );
03519     jscode = KStringHandler::rsqueeze( jscode, 80 ); // truncate if too long
03520     if (url.startsWith("javascript:window.open"))
03521       jscode += i18n(" (In new window)");
03522     setStatusBarText( Qt::escape( jscode ), BarHoverText );
03523     return;
03524   }
03525 
03526   KFileItem item(u, QString(), KFileItem::Unknown);
03527   emit d->m_extension->mouseOverInfo(item);
03528 
03529   QString com;
03530 
03531   KMimeType::Ptr typ = KMimeType::findByUrl( u );
03532 
03533   if ( typ )
03534     com = typ->comment( u );
03535 
03536   if ( !u.isValid() ) {
03537     setStatusBarText(Qt::escape(u.prettyUrl()), BarHoverText);
03538     return;
03539   }
03540 
03541   if ( u.isLocalFile() )
03542   {
03543     // TODO : use KIO::stat() and create a KFileItem out of its result,
03544     // to use KFileItem::statusBarText()
03545     const QString path = QFile::encodeName( u.toLocalFile() );
03546 
03547     KDE_struct_stat buff;
03548     bool ok = !KDE::stat( path, &buff );
03549 
03550     KDE_struct_stat lbuff;
03551     if (ok) ok = !KDE::lstat( path, &lbuff );
03552 
03553     QString text = Qt::escape(u.prettyUrl());
03554     QString text2 = text;
03555 
03556     if (ok && S_ISLNK( lbuff.st_mode ) )
03557     {
03558       QString tmp;
03559       if ( com.isNull() )
03560         tmp = i18n( "Symbolic Link");
03561       else
03562         tmp = i18n("%1 (Link)", com);
03563       char buff_two[1024];
03564       text += " -> ";
03565       int n = readlink ( path.toLocal8Bit().data(), buff_two, 1022);
03566       if (n == -1)
03567       {
03568         text2 += "  ";
03569         text2 += tmp;
03570         setStatusBarText(text2, BarHoverText);
03571         return;
03572       }
03573       buff_two[n] = 0;
03574 
03575       text += buff_two;
03576       text += "  ";
03577       text += tmp;
03578     }
03579     else if ( ok && S_ISREG( buff.st_mode ) )
03580     {
03581       if (buff.st_size < 1024)
03582         text = i18np("%2 (%1 byte)", "%2 (%1 bytes)", (long) buff.st_size, text2); // always put the URL last, in case it contains '%'
03583       else
03584       {
03585         float d = (float) buff.st_size/1024.0;
03586         text = i18n("%2 (%1 K)", KGlobal::locale()->formatNumber(d, 2), text2); // was %.2f
03587       }
03588       text += "  ";
03589       text += com;
03590     }
03591     else if ( ok && S_ISDIR( buff.st_mode ) )
03592     {
03593       text += "  ";
03594       text += com;
03595     }
03596     else
03597     {
03598       text += "  ";
03599       text += com;
03600     }
03601     setStatusBarText(text, BarHoverText);
03602   }
03603   else
03604   {
03605     QString extra;
03606     if (target.toLower() == "_blank")
03607     {
03608       extra = i18n(" (In new window)");
03609     }
03610     else if (!target.isEmpty() &&
03611              (target.toLower() != "_top") &&
03612              (target.toLower() != "_self") &&
03613              (target.toLower() != "_parent"))
03614     {
03615       KHTMLPart *p = this;
03616       while (p->parentPart())
03617           p = p->parentPart();
03618       if (!p->frameExists(target))
03619         extra = i18n(" (In new window)");
03620       else
03621         extra = i18n(" (In other frame)");
03622     }
03623 
03624     if (u.protocol() == QLatin1String("mailto")) {
03625       QString mailtoMsg /* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
03626       mailtoMsg += i18n("Email to: ") + KUrl::fromPercentEncoding(u.path().toLatin1());
03627       const QStringList queries = u.query().mid(1).split('&');
03628       QStringList::ConstIterator it = queries.begin();
03629       const QStringList::ConstIterator itEnd = queries.end();
03630       for (; it != itEnd; ++it)
03631         if ((*it).startsWith(QLatin1String("subject=")))
03632           mailtoMsg += i18n(" - Subject: ") + KUrl::fromPercentEncoding((*it).mid(8).toLatin1());
03633         else if ((*it).startsWith(QLatin1String("cc=")))
03634           mailtoMsg += i18n(" - CC: ") + KUrl::fromPercentEncoding((*it).mid(3).toLatin1());
03635         else if ((*it).startsWith(QLatin1String("bcc=")))
03636           mailtoMsg += i18n(" - BCC: ") + KUrl::fromPercentEncoding((*it).mid(4).toLatin1());
03637       mailtoMsg = Qt::escape(mailtoMsg);
03638       mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString());
03639       setStatusBarText("<qt>"+mailtoMsg, BarHoverText);
03640       return;
03641     }
03642    // Is this check necessary at all? (Frerich)
03643 #if 0
03644     else if (u.protocol() == QLatin1String("http")) {
03645         DOM::Node hrefNode = nodeUnderMouse().parentNode();
03646         while (hrefNode.nodeName().string() != QLatin1String("A") && !hrefNode.isNull())
03647           hrefNode = hrefNode.parentNode();
03648 
03649         if (!hrefNode.isNull()) {
03650           DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
03651           if (!hreflangNode.isNull()) {
03652             QString countryCode = hreflangNode.nodeValue().string().toLower();
03653             // Map the language code to an appropriate country code.
03654             if (countryCode == QLatin1String("en"))
03655               countryCode = QLatin1String("gb");
03656             QString flagImg = QLatin1String("<img src=%1>").arg(
03657                 locate("locale", QLatin1String("l10n/")
03658                 + countryCode
03659                 + QLatin1String("/flag.png")));
03660             emit setStatusBarText(flagImg + u.prettyUrl() + extra);
03661           }
03662         }
03663       }
03664 #endif
03665     setStatusBarText(Qt::escape(u.prettyUrl()) + extra, BarHoverText);
03666   }
03667 }
03668 
03669 //
03670 // This executes in the active part on a click or other url selection action in
03671 // that active part.
03672 //
03673 bool KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target, const KParts::OpenUrlArguments& _args, const KParts::BrowserArguments& _browserArgs )
03674 {
03675   KParts::OpenUrlArguments args = _args;
03676   KParts::BrowserArguments browserArgs = _browserArgs;
03677   bool hasTarget = false;
03678 
03679   QString target = _target;
03680   if ( target.isEmpty() && d->m_doc )
03681     target = d->m_doc->baseTarget();
03682   if ( !target.isEmpty() )
03683       hasTarget = true;
03684 
03685   if ( d->isJavaScriptURL(url) )
03686   {
03687     crossFrameExecuteScript( target, d->codeForJavaScriptURL(url) );
03688     return false;
03689   }
03690 
03691   KUrl cURL = completeURL(url);
03692   // special case for <a href="">  (IE removes filename, mozilla doesn't)
03693   if ( url.isEmpty() )
03694     cURL.setFileName( url ); // removes filename
03695 
03696   if ( !cURL.isValid() )
03697     // ### ERROR HANDLING
03698     return false;
03699 
03700   kDebug(6050) << this << "complete URL:" << cURL.url() << "target=" << target;
03701 
03702   if ( state & Qt::ControlModifier )
03703   {
03704     emit d->m_extension->createNewWindow( cURL, args, browserArgs );
03705     return true;
03706   }
03707 
03708   if ( button == Qt::LeftButton && ( state & Qt::ShiftModifier ) )
03709   {
03710     KIO::MetaData metaData;
03711     metaData.insert( "referrer", d->m_referrer );
03712     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), cURL, metaData );
03713     return false;
03714   }
03715 
03716   if (!checkLinkSecurity(cURL,
03717                          ki18n( "<qt>This untrusted page links to<br /><b>%1</b>.<br />Do you want to follow the link?</qt>" ),
03718                          i18n( "Follow" )))
03719     return false;
03720 
03721   browserArgs.frameName = target;
03722 
03723   args.metaData().insert("main_frame_request",
03724                          parentPart() == 0 ? "TRUE":"FALSE");
03725   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
03726   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
03727   args.metaData().insert("PropagateHttpHeader", "true");
03728   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
03729   args.metaData().insert("ssl_activate_warnings", "TRUE");
03730 
03731   if ( hasTarget && target != "_self" && target != "_top" && target != "_blank" && target != "_parent" )
03732   {
03733     // unknown frame names should open in a new window.
03734     khtml::ChildFrame *frame = recursiveFrameRequest( this, cURL, args, browserArgs, false );
03735     if ( frame )
03736     {
03737       args.metaData()["referrer"] = d->m_referrer;
03738       requestObject( frame, cURL, args, browserArgs );
03739       return true;
03740     }
03741   }
03742 
03743   if (!d->m_referrer.isEmpty() && !args.metaData().contains("referrer"))
03744     args.metaData()["referrer"] = d->m_referrer;
03745 
03746   if ( button == Qt::NoButton && (state & Qt::ShiftModifier) && (state & Qt::ControlModifier) )
03747   {
03748     emit d->m_extension->createNewWindow( cURL, args, browserArgs );
03749     return true;
03750   }
03751 
03752   if ( state & Qt::ShiftModifier)
03753   {
03754     KParts::WindowArgs winArgs;
03755     winArgs.setLowerWindow(true);
03756     emit d->m_extension->createNewWindow( cURL, args, browserArgs, winArgs );
03757     return true;
03758   }
03759 
03760   //If we're asked to open up an anchor in the current URL, in current window,
03761   //merely gotoanchor, and do not reload the new page. Note that this does
03762   //not apply if the URL is the same page, but without a ref
03763   if (cURL.hasRef() && (!hasTarget || target == "_self"))
03764   {
03765     if (d->isLocalAnchorJump(cURL))
03766     {
03767       d->executeAnchorJump(cURL, browserArgs.lockHistory() );
03768       return false; // we jumped, but we didn't open a URL
03769     }
03770   }
03771 
03772   if ( !d->m_bComplete && !hasTarget )
03773     closeUrl();
03774 
03775   view()->viewport()->unsetCursor();
03776   emit d->m_extension->openUrlRequest( cURL, args, browserArgs );
03777   return true;
03778 }
03779 
03780 void KHTMLPart::slotViewDocumentSource()
03781 {
03782   KUrl currentUrl(this->url());
03783   bool isTempFile = false;
03784   if (!(currentUrl.isLocalFile()) && KHTMLPageCache::self()->isComplete(d->m_cacheId))
03785   {
03786      KTemporaryFile sourceFile;
03787      sourceFile.setSuffix(defaultExtension());
03788      sourceFile.setAutoRemove(false);
03789      if (sourceFile.open())
03790      {
03791         QDataStream stream ( &sourceFile );
03792         KHTMLPageCache::self()->saveData(d->m_cacheId, &stream);
03793         currentUrl = KUrl();
03794         currentUrl.setPath(sourceFile.fileName());
03795         isTempFile = true;
03796      }
03797   }
03798 
03799   (void) KRun::runUrl( currentUrl, QLatin1String("text/plain"), view(), isTempFile );
03800 }
03801 
03802 void KHTMLPart::slotViewPageInfo()
03803 {
03804   Ui_KHTMLInfoDlg ui;
03805 
03806   QDialog *dlg = new QDialog(0);
03807   dlg->setAttribute(Qt::WA_DeleteOnClose);
03808   dlg->setObjectName("KHTML Page Info Dialog");
03809   ui.setupUi(dlg);
03810 
03811   ui._close->setGuiItem(KStandardGuiItem::close());
03812 
03813   connect(ui._close, SIGNAL(clicked()), dlg, SLOT(accept()));
03814   if (d->m_doc)
03815      ui._title->setText(d->m_doc->title().string());
03816 
03817   // If it's a frame, set the caption to "Frame Information"
03818   if ( parentPart() && d->m_doc && d->m_doc->isHTMLDocument() ) {
03819      dlg->setWindowTitle(i18n("Frame Information"));
03820   }
03821 
03822   QString editStr;
03823 
03824   if (!d->m_pageServices.isEmpty())
03825     editStr = i18n("   <a href=\"%1\">[Properties]</a>", d->m_pageServices);
03826 
03827   QString squeezedURL = KStringHandler::csqueeze( url().prettyUrl(), 80 );
03828   ui._url->setText("<a href=\"" + url().url() + "\">" + squeezedURL + "</a>" + editStr);
03829   if (lastModified().isEmpty())
03830   {
03831     ui._lastModified->hide();
03832     ui._lmLabel->hide();
03833   }
03834   else
03835     ui._lastModified->setText(lastModified());
03836 
03837   const QString& enc = encoding();
03838   if (enc.isEmpty()) {
03839     ui._eLabel->hide();
03840     ui._encoding->hide();
03841   } else {
03842     ui._encoding->setText(enc);
03843   }
03844 
03845   if (!xmlDocImpl() || xmlDocImpl()->parseMode() == DOM::DocumentImpl::Unknown) {
03846     ui._mode->hide();
03847     ui._modeLabel->hide();
03848   } else {
03849     switch (xmlDocImpl()->parseMode()) {
03850       case DOM::DocumentImpl::Compat:
03851         ui._mode->setText(i18nc("HTML rendering mode (see http://en.wikipedia.org/wiki/Quirks_mode)", "Quirks"));
03852         break;
03853       case DOM::DocumentImpl::Transitional:
03854         ui._mode->setText(i18nc("HTML rendering mode (see http://en.wikipedia.org/wiki/Quirks_mode)", "Almost standards"));
03855         break;
03856       case DOM::DocumentImpl::Strict:
03857       default: // others handled above
03858         ui._mode->setText(i18nc("HTML rendering mode (see http://en.wikipedia.org/wiki/Quirks_mode)", "Strict"));
03859         break;
03860     }
03861   }
03862 
03863   /* populate the list view now */
03864   const QStringList headers = d->m_httpHeaders.split("\n");
03865 
03866   QStringList::ConstIterator it = headers.begin();
03867   const QStringList::ConstIterator itEnd = headers.end();
03868 
03869   for (; it != itEnd; ++it) {
03870     const QStringList header = (*it).split(QRegExp(":[ ]+"));
03871     if (header.count() != 2)
03872        continue;
03873     QTreeWidgetItem *item = new QTreeWidgetItem(ui._headers);
03874     item->setText(0, header[0]);
03875     item->setText(1, header[1]);
03876   }
03877 
03878   dlg->show();
03879   /* put no code here */
03880 }
03881 
03882 
03883 void KHTMLPart::slotViewFrameSource()
03884 {
03885   KParts::ReadOnlyPart *frame = currentFrame();
03886   if ( !frame )
03887     return;
03888 
03889   KUrl url = frame->url();
03890   bool isTempFile = false;
03891   if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
03892   {
03893        long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
03894 
03895        if (KHTMLPageCache::self()->isComplete(cacheId))
03896        {
03897            KTemporaryFile sourceFile;
03898            sourceFile.setSuffix(defaultExtension());
03899            sourceFile.setAutoRemove(false);
03900            if (sourceFile.open())
03901            {
03902                QDataStream stream ( &sourceFile );
03903                KHTMLPageCache::self()->saveData(cacheId, &stream);
03904                url = KUrl();
03905                url.setPath(sourceFile.fileName());
03906                isTempFile = true;
03907            }
03908      }
03909   }
03910 
03911   (void) KRun::runUrl( url, QLatin1String("text/plain"), view(), isTempFile );
03912 }
03913 
03914 KUrl KHTMLPart::backgroundURL() const
03915 {
03916   // ### what about XML documents? get from CSS?
03917   if (!d->m_doc || !d->m_doc->isHTMLDocument())
03918     return KUrl();
03919 
03920   QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
03921 
03922   return KUrl( url(), relURL );
03923 }
03924 
03925 void KHTMLPart::slotSaveBackground()
03926 {
03927   KIO::MetaData metaData;
03928   metaData["referrer"] = d->m_referrer;
03929   KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save Background Image As"), backgroundURL(), metaData );
03930 }
03931 
03932 void KHTMLPart::slotSaveDocument()
03933 {
03934   KUrl srcURL( url() );
03935 
03936   if ( srcURL.fileName(KUrl::ObeyTrailingSlash).isEmpty() )
03937     srcURL.setFileName( "index" + defaultExtension() );
03938 
03939   KIO::MetaData metaData;
03940   // Referre unknown?
03941   KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, "text/html", d->m_cacheId );
03942 }
03943 
03944 void KHTMLPart::slotSecurity()
03945 {
03946 //   kDebug( 6050 ) << "Meta Data:" << endl
03947 //                   << d->m_ssl_peer_cert_subject
03948 //                   << endl
03949 //                   << d->m_ssl_peer_cert_issuer
03950 //                   << endl
03951 //                   << d->m_ssl_cipher
03952 //                   << endl
03953 //                   << d->m_ssl_cipher_desc
03954 //                   << endl
03955 //                   << d->m_ssl_cipher_version
03956 //                   << endl
03957 //                   << d->m_ssl_good_from
03958 //                   << endl
03959 //                   << d->m_ssl_good_until
03960 //                   << endl
03961 //                   << d->m_ssl_cert_state
03962 //                   << endl;
03963 
03964   //### reenable with new signature
03965 #if 0
03966   KSslInfoDialog *kid = new KSslInfoDialog(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
03967 
03968   const QStringList sl = d->m_ssl_peer_chain.split('\n', QString::SkipEmptyParts);
03969   QList<QSslCertificate> certChain;
03970   bool certChainOk = d->m_ssl_in_use;
03971   if (certChainOk) {
03972     foreach (const QString &s, sl) {
03973       certChain.append(QSslCertificate(s.toAscii())); //or is it toLocal8Bit or whatever?
03974       if (certChain.last().isNull()) {
03975         certChainOk = false;
03976         break;
03977       }
03978     }
03979   }
03980   if (certChainOk) {
03981     kid->setup(certChain,
03982                d->m_ssl_peer_ip,
03983                url().url(),
03984                d->m_ssl_cipher,
03985                d->m_ssl_cipher_desc,
03986                d->m_ssl_cipher_version,
03987                d->m_ssl_cipher_used_bits.toInt(),
03988                d->m_ssl_cipher_bits.toInt(),
03989                (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt());
03990   }
03991   kid->exec();
03992   //the dialog deletes itself on close
03993 #endif
03994 
03995     KSslInfoDialog *kid = new KSslInfoDialog(0);
03996     //### This is boilerplate code and it's copied from SlaveInterface.
03997     QStringList sl = d->m_ssl_peer_chain.split('\x01', QString::SkipEmptyParts);
03998     QList<QSslCertificate> certChain;
03999     bool decodedOk = true;
04000     foreach (const QString &s, sl) {
04001         certChain.append(QSslCertificate(s.toAscii())); //or is it toLocal8Bit or whatever?
04002         if (certChain.last().isNull()) {
04003             decodedOk = false;
04004             break;
04005         }
04006     }
04007 
04008     if (decodedOk || true /*H4X*/) {
04009         kid->setSslInfo(certChain,
04010                         d->m_ssl_peer_ip,
04011                         url().host(),
04012                         d->m_ssl_protocol_version,
04013                         d->m_ssl_cipher,
04014                         d->m_ssl_cipher_used_bits.toInt(),
04015                         d->m_ssl_cipher_bits.toInt(),
04016                         KSslInfoDialog::errorsFromString(d->m_ssl_cert_errors));
04017         kDebug(7024) << "Showing SSL Info dialog";
04018         kid->exec();
04019         kDebug(7024) << "SSL Info dialog closed";
04020     } else {
04021         KMessageBox::information(0, i18n("The peer SSL certificate chain "
04022                                          "appears to be corrupt."),
04023                                  i18n("SSL"));
04024     }
04025 }
04026 
04027 void KHTMLPart::slotSaveFrame()
04028 {
04029     KParts::ReadOnlyPart *frame = currentFrame();
04030     if ( !frame )
04031         return;
04032 
04033     KUrl srcURL( frame->url() );
04034 
04035         if ( srcURL.fileName(KUrl::ObeyTrailingSlash).isEmpty() )
04036         srcURL.setFileName( "index" + defaultExtension() );
04037 
04038     KIO::MetaData metaData;
04039     // Referrer unknown?
04040     KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save Frame As" ), srcURL, metaData, "text/html" );
04041 }
04042 
04043 void KHTMLPart::slotSetEncoding(const QString &enc)
04044 {
04045     d->m_autoDetectLanguage=KEncodingDetector::None;
04046     setEncoding( enc, true);
04047 }
04048 
04049 void KHTMLPart::slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript scri)
04050 {
04051   d->m_autoDetectLanguage=scri;
04052   setEncoding( QString(), false );
04053 }
04054 
04055 void KHTMLPart::slotUseStylesheet()
04056 {
04057   if (d->m_doc)
04058   {
04059     bool autoselect = (d->m_paUseStylesheet->currentItem() == 0);
04060     d->m_sheetUsed = autoselect ? QString() : d->m_paUseStylesheet->currentText();
04061     d->m_doc->updateStyleSelector();
04062   }
04063 }
04064 
04065 void KHTMLPart::updateActions()
04066 {
04067   bool frames = false;
04068 
04069   QList<khtml::ChildFrame*>::ConstIterator it = d->m_frames.constBegin();
04070   const QList<khtml::ChildFrame*>::ConstIterator end = d->m_frames.constEnd();
04071   for (; it != end; ++it )
04072       if ( (*it)->m_type == khtml::ChildFrame::Frame )
04073       {
04074           frames = true;
04075           break;
04076       }
04077 
04078   if (d->m_paViewFrame)
04079     d->m_paViewFrame->setEnabled( frames );
04080   if (d->m_paSaveFrame)
04081     d->m_paSaveFrame->setEnabled( frames );
04082 
04083   if ( frames )
04084     d->m_paFind->setText( i18n( "&Find in Frame..." ) );
04085   else
04086     d->m_paFind->setText( i18n( "&Find..." ) );
04087 
04088   KParts::Part *frame = 0;
04089 
04090   if ( frames )
04091     frame = currentFrame();
04092 
04093   bool enableFindAndSelectAll = true;
04094 
04095   if ( frame )
04096     enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
04097 
04098   d->m_paFind->setEnabled( enableFindAndSelectAll );
04099   d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
04100 
04101   bool enablePrintFrame = false;
04102 
04103   if ( frame )
04104   {
04105     QObject *ext = KParts::BrowserExtension::childObject( frame );
04106     if ( ext )
04107       enablePrintFrame = ext->metaObject()->indexOfSlot( "print()" ) != -1;
04108   }
04109 
04110   d->m_paPrintFrame->setEnabled( enablePrintFrame );
04111 
04112   QString bgURL;
04113 
04114   // ### frames
04115   if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
04116     bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
04117 
04118   if (d->m_paSaveBackground)
04119     d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
04120 
04121   if ( d->m_paDebugScript )
04122     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
04123 }
04124 
04125 KParts::ScriptableExtension *KHTMLPart::scriptableExtension( const DOM::NodeImpl *frame) {
04126     const ConstFrameIt end = d->m_objects.constEnd();
04127     for(ConstFrameIt it = d->m_objects.constBegin(); it != end; ++it )
04128         if ((*it)->m_partContainerElement.data() == frame)
04129             return (*it)->m_scriptable.data();
04130     return 0L;
04131 }
04132 
04133 void KHTMLPart::loadFrameElement( DOM::HTMLPartContainerElementImpl *frame, const QString &url,
04134                                   const QString &frameName, const QStringList &params, bool isIFrame )
04135 {
04136     //kDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )";
04137     khtml::ChildFrame* child;
04138 
04139     FrameIt it = d->m_frames.find( frameName );
04140     if ( it == d->m_frames.end() ) {
04141         child = new khtml::ChildFrame;
04142         //kDebug( 6050 ) << "inserting new frame into frame map " << frameName;
04143         child->m_name = frameName;
04144         d->m_frames.insert( d->m_frames.end(), child );
04145     } else {
04146         child = *it;
04147     }
04148 
04149     child->m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
04150     child->m_partContainerElement = frame;
04151     child->m_params = params;
04152 
04153     // If we do not have a part, make sure we create one.
04154     if (!child->m_part) {
04155         QStringList dummy; // the list of servicetypes handled by the part is now unused.
04156         QString     khtml = QString::fromLatin1("khtml");
04157         KParts::ReadOnlyPart* part = createPart(d->m_view->viewport(), this,
04158                                                 QString::fromLatin1("text/html"),
04159                                                 khtml, dummy, QStringList());
04160         // We navigate it to about:blank to setup an empty one, but we do it
04161         // before hooking up the signals and extensions, so that any sync emit
04162         // of completed by the kid doesn't cause us to be marked as completed.
04163         // (async ones are discovered by the presence of the KHTMLRun)
04164         // ### load event on the kid?
04165         navigateLocalProtocol(child, part, KUrl("about:blank"));
04166         connectToChildPart(child, part, "text/html" /* mimetype of the part, not what's being loaded */);
04167     }
04168 
04169     KUrl u = url.isEmpty() ? KUrl() : completeURL( url );
04170 
04171     // Since we don't specify args here a KHTMLRun will be used to determine the
04172     // mimetype, which will then be  passed down at the bottom of processObjectRequest
04173     // inside URLArgs to the part. In our particular case, this means that we can
04174     // use that inside KHTMLPart::openUrl to route things appropriately.
04175     child->m_bCompleted = false;
04176     if (!requestObject( child, u ) && !child->m_run) {
04177         child->m_bCompleted = true;
04178     }
04179 }
04180 
04181 QString KHTMLPart::requestFrameName()
04182 {
04183    return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
04184 }
04185 
04186 bool KHTMLPart::loadObjectElement( DOM::HTMLPartContainerElementImpl *frame, const QString &url,
04187                                    const QString &serviceType, const QStringList &params )
04188 {
04189   //kDebug( 6031 ) << this << "frame=" << frame;
04190   khtml::ChildFrame *child = new khtml::ChildFrame;
04191   FrameIt it = d->m_objects.insert( d->m_objects.end(), child );
04192   (*it)->m_partContainerElement = frame;
04193   (*it)->m_type = khtml::ChildFrame::Object;
04194   (*it)->m_params = params;
04195 
04196   KParts::OpenUrlArguments args;
04197   args.setMimeType(serviceType);
04198   if (!requestObject( *it, completeURL( url ), args ) && !(*it)->m_run) {
04199       (*it)->m_bCompleted = true;
04200       return false;
04201   }
04202   return true;
04203 }
04204 
04205 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KUrl &url, const KParts::OpenUrlArguments &_args,
04206                                const KParts::BrowserArguments& browserArgs )
04207 {
04208   // we always permit javascript: URLs here since they're basically just
04209   // empty pages (and checkLinkSecurity/KAuthorized doesn't know what to do with them)
04210   if (!d->isJavaScriptURL(url.url()) && !checkLinkSecurity(url))
04211   {
04212     kDebug(6031) << this << "checkLinkSecurity refused";
04213     return false;
04214   }
04215 
04216   if (d->m_bClearing)
04217   {
04218     return false;
04219   }
04220 
04221   if ( child->m_bPreloaded )
04222   {
04223     if ( child->m_partContainerElement && child->m_part )
04224       child->m_partContainerElement.data()->setWidget( child->m_part.data()->widget() );
04225 
04226     child->m_bPreloaded = false;
04227     return true;
04228   }
04229 
04230   //kDebug(6031) << "child=" << child << "child->m_part=" << child->m_part;
04231 
04232   KParts::OpenUrlArguments args( _args );
04233 
04234   if ( child->m_run ) {
04235       kDebug(6031) << "navigating ChildFrame while mimetype resolution was in progress...";
04236       child->m_run.data()->abort();
04237   }
04238 
04239   // ### Dubious -- the whole dir/ vs. img thing
04240   if ( child->m_part && !args.reload() && child->m_part.data()->url().equals( url,
04241               KUrl::CompareWithoutTrailingSlash | KUrl::CompareWithoutFragment | KUrl::AllowEmptyPath ) )
04242     args.setMimeType(child->m_serviceType);
04243 
04244   child->m_browserArgs = browserArgs;
04245   child->m_args = args;
04246 
04247   // reload/soft-reload arguments are always inherited from parent
04248   child->m_args.setReload( arguments().reload() );
04249   child->m_browserArgs.softReload = d->m_extension->browserArguments().softReload;
04250 
04251   child->m_serviceName.clear();
04252   if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
04253     child->m_args.metaData()["referrer"] = d->m_referrer;
04254 
04255   child->m_args.metaData().insert("PropagateHttpHeader", "true");
04256   child->m_args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04257   child->m_args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04258   child->m_args.metaData().insert("main_frame_request",
04259                                   parentPart() == 0 ? "TRUE":"FALSE");
04260   child->m_args.metaData().insert("ssl_was_in_use",
04261                                   d->m_ssl_in_use ? "TRUE":"FALSE");
04262   child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
04263   child->m_args.metaData().insert("cross-domain", toplevelURL().url());
04264 
04265   // We know the frame will be text/html if the HTML says <frame src=""> or <frame src="about:blank">,
04266   // no need to KHTMLRun to figure out the mimetype"
04267   // ### What if we're inside an XML document?
04268   if ((url.isEmpty() || url.url() == "about:blank" || url.protocol() == "javascript") && args.mimeType().isEmpty())
04269     args.setMimeType(QLatin1String("text/html"));
04270 
04271   if ( args.mimeType().isEmpty() ) {
04272     kDebug(6031) << "Running new KHTMLRun for" << this << "and child=" << child;
04273     child->m_run = new KHTMLRun( this, child, url, child->m_args, child->m_browserArgs, true );
04274     d->m_bComplete = false; // ensures we stop it in checkCompleted...
04275     return false;
04276   } else {
04277     return processObjectRequest( child, url, args.mimeType() );
04278   }
04279 }
04280 
04281 void KHTMLPart::childLoadFailure( khtml::ChildFrame *child )
04282 {
04283   child->m_bCompleted = true;
04284   if ( child->m_partContainerElement )
04285     child->m_partContainerElement.data()->partLoadingErrorNotify();
04286 
04287   checkCompleted();
04288 }
04289 
04290 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KUrl &_url, const QString &mimetype )
04291 {
04292     kDebug( 6031 ) << "trying to create part for" << mimetype << _url;
04293 
04294     // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
04295     // by an emitting frame part (emit openUrlRequest( blahurl, ... ) . A few lines below we delete the part
04296     // though -> the reference becomes invalid -> crash is likely
04297     KUrl url( _url );
04298 
04299     // khtmlrun called us with empty url + mimetype to indicate a loading error,
04300     // we obviosuly failed; but we can return true here since we don't want it
04301     // doing anything more, while childLoadFailure is enough to notify our kid.
04302     if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) ) {
04303         childLoadFailure(child);
04304         return true;
04305     }
04306 
04307     // we also want to ignore any spurious requests due to closing when parser is being cleared. These should be
04308     // ignored entirely  --- the tail end of ::clear will clean things up.
04309     if (d->m_bClearing)
04310         return false;
04311 
04312     if (child->m_bNotify) {
04313         child->m_bNotify = false;
04314         if ( !child->m_browserArgs.lockHistory() )
04315             emit d->m_extension->openUrlNotify();
04316     }
04317 
04318     // Now, depending on mimetype and current state of the world, we may have
04319     // to create a new part or ask the user to save things, etc.
04320     //
04321     // We need a new part if there isn't one at all (doh) or the one that's there
04322     // is not for the mimetype we're loading.
04323     //
04324     // For these new types, we may have to ask the user to save it or not
04325     // (we don't if it's navigating the same type).
04326     // Further, we will want to ask if content-disposition suggests we ask for
04327     // saving, even if we're re-navigating.
04328     if ( !child->m_part || child->m_serviceType != mimetype ||
04329             (child->m_run && child->m_run.data()->serverSuggestsSave())) {
04330         // We often get here if we didn't know the mimetype in advance, and had to rely
04331         // on KRun to figure it out. In this case, we let the element check if it wants to
04332         // handle this mimetype itself, for e.g. objects containing images.
04333         if ( child->m_partContainerElement &&
04334                 child->m_partContainerElement.data()->mimetypeHandledInternally(mimetype) ) {
04335             child->m_bCompleted = true;
04336             checkCompleted();
04337             return true;
04338         }
04339 
04340         // Before attempting to load a part, check if the user wants that.
04341         // Many don't like getting ZIP files embedded.
04342         // However we don't want to ask for flash and other plugin things.
04343         //
04344         // Note: this is fine for frames, since we will merely effectively ignore
04345         // the navigation if this happens
04346         if ( child->m_type != khtml::ChildFrame::Object && child->m_type != khtml::ChildFrame::IFrame ) {
04347             QString suggestedFileName;
04348             int disposition = 0;
04349             if ( KHTMLRun* run = child->m_run.data() ) {
04350                 suggestedFileName = run->suggestedFileName();
04351                 disposition = run->serverSuggestsSave() ?
04352                                  KParts::BrowserRun::AttachmentDisposition :
04353                                  KParts::BrowserRun::InlineDisposition;
04354             }
04355 
04356             KParts::BrowserOpenOrSaveQuestion dlg( widget(), url, mimetype );
04357             dlg.setSuggestedFileName( suggestedFileName );
04358             const KParts::BrowserOpenOrSaveQuestion::Result res = dlg.askEmbedOrSave( disposition );
04359 
04360             switch( res ) {
04361             case KParts::BrowserOpenOrSaveQuestion::Save:
04362                 KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url, child->m_args.metaData(), QString(), 0, suggestedFileName );
04363                 // fall-through
04364             case KParts::BrowserOpenOrSaveQuestion::Cancel:
04365                 child->m_bCompleted = true;
04366                 checkCompleted();
04367                 return true; // done
04368             default: // Embed
04369                 break;
04370             }
04371         }
04372 
04373         // Now, for frames and iframes, we always create a KHTMLPart anyway,
04374         // doing it in advance when registering the frame. So we want the
04375         // actual creation only for objects here.
04376         if ( child->m_type == khtml::ChildFrame::Object ) {
04377             KMimeType::Ptr mime = KMimeType::mimeType(mimetype);
04378             if (mime) {
04379                 // Even for objects, however, we want to force a KHTMLPart for
04380                 // html & xml, even  if the normally preferred part is another one,
04381                 // so that we can script the target natively via contentDocument method.
04382                 if (mime->is("text/html")
04383                     || mime->is("application/xml")) { // this includes xhtml and svg
04384                     child->m_serviceName = "khtml";
04385                 }
04386             }
04387 
04388             QStringList dummy; // the list of servicetypes handled by the part is now unused.
04389             KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), this, mimetype, child->m_serviceName, dummy, child->m_params );
04390 
04391             if ( !part ) {
04392                 childLoadFailure(child);
04393                 return false;
04394             }
04395 
04396             connectToChildPart( child, part, mimetype );
04397         }
04398     }
04399 
04400     checkEmitLoadEvent();
04401 
04402     // Some JS code in the load event may have destroyed the part
04403     // In that case, abort
04404     if ( !child->m_part )
04405         return false;
04406 
04407     if ( child->m_bPreloaded ) {
04408         if ( child->m_partContainerElement && child->m_part )
04409             child->m_partContainerElement.data()->setWidget( child->m_part.data()->widget() );
04410 
04411         child->m_bPreloaded = false;
04412         return true;
04413     }
04414 
04415     // reload/soft-reload arguments are always inherited from parent
04416     child->m_args.setReload( arguments().reload() );
04417     child->m_browserArgs.softReload = d->m_extension->browserArguments().softReload;
04418 
04419     // make sure the part has a way to find out about the mimetype.
04420     // we actually set it in child->m_args in requestObject already,
04421     // but it's useless if we had to use a KHTMLRun instance, as the
04422     // point the run object is to find out exactly the mimetype.
04423     child->m_args.setMimeType(mimetype);
04424     child->m_part.data()->setArguments( child->m_args );
04425 
04426     // if not a frame set child as completed
04427     // ### dubious.
04428     child->m_bCompleted = child->m_type == khtml::ChildFrame::Object;
04429 
04430     if ( child->m_extension )
04431         child->m_extension.data()->setBrowserArguments( child->m_browserArgs );
04432 
04433     return navigateChild( child, url );
04434 }
04435 
04436 bool KHTMLPart::navigateLocalProtocol( khtml::ChildFrame* /*child*/, KParts::ReadOnlyPart *inPart,
04437                                        const KUrl& url )
04438 {
04439     if (!qobject_cast<KHTMLPart*>(inPart))
04440         return false;
04441 
04442     KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(inPart));
04443 
04444     p->begin();
04445 
04446     // We may have to re-propagate the domain here if we go here due to navigation
04447     d->propagateInitialDomainAndBaseTo(p);
04448 
04449     // Support for javascript: sources
04450     if (d->isJavaScriptURL(url.url())) {
04451         // See if we want to replace content with javascript: output..
04452         QVariant res = p->executeScript( DOM::Node(),
04453                                         d->codeForJavaScriptURL(url.url()));
04454         if (res.type() == QVariant::String && p->d->m_redirectURL.isEmpty()) {
04455             p->begin();
04456             p->setAlwaysHonourDoctype(); // Disable public API compat; it messes with doctype
04457             // We recreated the document, so propagate domain again.
04458             d->propagateInitialDomainAndBaseTo(p);
04459             p->write( res.toString() );
04460             p->end();
04461         }
04462     } else {
04463         p->setUrl(url);
04464         // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
04465         p->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
04466     }
04467     p->end();
04468     // we don't need to worry about child completion explicitly for KHTMLPart...
04469     // or do we?
04470     return true;
04471 }
04472 
04473 bool KHTMLPart::navigateChild( khtml::ChildFrame *child, const KUrl& url )
04474 {
04475     if (url.protocol() == "javascript" || url.url() == "about:blank") {
04476         return navigateLocalProtocol(child, child->m_part.data(), url);
04477     } else if ( !url.isEmpty() ) {
04478         kDebug( 6031 ) << "opening" << url << "in frame" << child->m_part;
04479         bool b = child->m_part.data()->openUrl( url );
04480         if (child->m_bCompleted)
04481             checkCompleted();
04482         return b;
04483     } else {
04484         // empty URL -> no need to navigate
04485         child->m_bCompleted = true;
04486         checkCompleted();
04487         return true;
04488     }
04489 }
04490 
04491 void KHTMLPart::connectToChildPart( khtml::ChildFrame *child, KParts::ReadOnlyPart *part,
04492                                     const QString& mimetype)
04493 {
04494     kDebug(6031) << "we:" << this << "kid:" << child << part << mimetype;
04495 
04496     part->setObjectName( child->m_name );
04497 
04498     // Cleanup any previous part for this childframe and its connections
04499     if ( KParts::ReadOnlyPart* p = child->m_part.data() ) {
04500       if (!qobject_cast<KHTMLPart*>(p) && child->m_jscript)
04501           child->m_jscript->clear();
04502       partManager()->removePart( p );
04503       delete p;
04504       child->m_scriptable.clear();
04505     }
04506 
04507     child->m_part = part;
04508 
04509     child->m_serviceType = mimetype;
04510     if ( child->m_partContainerElement && part->widget() )
04511       child->m_partContainerElement.data()->setWidget( part->widget() );
04512 
04513     if ( child->m_type != khtml::ChildFrame::Object )
04514       partManager()->addPart( part, false );
04515 //  else
04516 //      kDebug(6031) << "AH! NO FRAME!!!!!";
04517 
04518     if (qobject_cast<KHTMLPart*>(part)) {
04519       static_cast<KHTMLPart*>(part)->d->m_frame = child;
04520     } else if (child->m_partContainerElement) {
04521       // See if this can be scripted..
04522       KParts::ScriptableExtension* scriptExt = KParts::ScriptableExtension::childObject(part);
04523       if (!scriptExt) {
04524         // Try to fall back to LiveConnectExtension compat
04525         KParts::LiveConnectExtension* lc = KParts::LiveConnectExtension::childObject(part);
04526         if (lc)
04527             scriptExt = KParts::ScriptableExtension::adapterFromLiveConnect(part, lc);
04528       }
04529 
04530       if (scriptExt)
04531         scriptExt->setHost(d->m_scriptableExtension);
04532       child->m_scriptable = scriptExt;
04533     }
04534     KParts::StatusBarExtension *sb = KParts::StatusBarExtension::childObject(part);
04535     if (sb)
04536       sb->setStatusBar( d->m_statusBarExtension->statusBar() );
04537 
04538     connect( part, SIGNAL( started( KIO::Job *) ),
04539              this, SLOT( slotChildStarted( KIO::Job *) ) );
04540     connect( part, SIGNAL( completed() ),
04541              this, SLOT( slotChildCompleted() ) );
04542     connect( part, SIGNAL( completed(bool) ),
04543              this, SLOT( slotChildCompleted(bool) ) );
04544     connect( part, SIGNAL( setStatusBarText( const QString & ) ),
04545                 this, SIGNAL( setStatusBarText( const QString & ) ) );
04546     if ( part->inherits( "KHTMLPart" ) )
04547     {
04548       connect( this, SIGNAL( completed() ),
04549                part, SLOT( slotParentCompleted() ) );
04550       connect( this, SIGNAL( completed(bool) ),
04551                part, SLOT( slotParentCompleted() ) );
04552       // As soon as the child's document is created, we need to set its domain
04553       // (but we do so only once, so it can't be simply done in the child)
04554       connect( part, SIGNAL( docCreated() ),
04555                this, SLOT( slotChildDocCreated() ) );
04556     }
04557 
04558     child->m_extension = KParts::BrowserExtension::childObject( part );
04559 
04560     if ( KParts::BrowserExtension* kidBrowserExt = child->m_extension.data() )
04561     {
04562       connect( kidBrowserExt, SIGNAL( openUrlNotify() ),
04563                d->m_extension, SIGNAL( openUrlNotify() ) );
04564 
04565       connect( kidBrowserExt, SIGNAL( openUrlRequestDelayed( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & ) ),
04566                this, SLOT( slotChildURLRequest( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & ) ) );
04567 
04568       connect( kidBrowserExt, SIGNAL( createNewWindow( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments &, const KParts::WindowArgs &, KParts::ReadOnlyPart ** ) ),
04569                d->m_extension, SIGNAL( createNewWindow( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & , const KParts::WindowArgs &, KParts::ReadOnlyPart **) ) );
04570 
04571       connect( kidBrowserExt, SIGNAL(popupMenu(QPoint,KFileItemList,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)),
04572              d->m_extension, SIGNAL(popupMenu(QPoint,KFileItemList,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)) );
04573       connect( kidBrowserExt, SIGNAL(popupMenu(QPoint,KUrl,mode_t,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)),
04574              d->m_extension, SIGNAL(popupMenu(QPoint,KUrl,mode_t,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)) );
04575 
04576       connect( kidBrowserExt, SIGNAL( infoMessage( const QString & ) ),
04577                d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
04578 
04579       connect( kidBrowserExt, SIGNAL( requestFocus( KParts::ReadOnlyPart * ) ),
04580                this, SLOT( slotRequestFocus( KParts::ReadOnlyPart * ) ) );
04581 
04582       kidBrowserExt->setBrowserInterface( d->m_extension->browserInterface() );
04583     }
04584 }
04585 
04586 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget,
04587                                              QObject *parent, const QString &mimetype,
04588                                              QString &serviceName, QStringList &serviceTypes,
04589                                              const QStringList &params )
04590 {
04591   QString constr;
04592   if ( !serviceName.isEmpty() )
04593     constr.append( QString::fromLatin1( "DesktopEntryName == '%1'" ).arg( serviceName ) );
04594 
04595   KService::List offers = KMimeTypeTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr );
04596 
04597   if ( offers.isEmpty() ) {
04598     int pos = mimetype.indexOf( "-plugin" );
04599     if (pos < 0)
04600         return 0L;
04601     QString stripped_mime = mimetype.left( pos );
04602     offers = KMimeTypeTrader::self()->query( stripped_mime, "KParts/ReadOnlyPart", constr );
04603     if ( offers.isEmpty() )
04604         return 0L;
04605   }
04606 
04607   KService::List::ConstIterator it = offers.constBegin();
04608   const KService::List::ConstIterator itEnd = offers.constEnd();
04609   for ( ; it != itEnd; ++it )
04610   {
04611     KService::Ptr service = (*it);
04612 
04613     KPluginLoader loader( *service, KHTMLGlobal::componentData() );
04614     KPluginFactory* const factory = loader.factory();
04615     if ( factory ) {
04616       // Turn params into a QVariantList as expected by KPluginFactory
04617       QVariantList variantlist;
04618       Q_FOREACH(const QString& str, params)
04619           variantlist << QVariant(str);
04620 
04621       if ( service->serviceTypes().contains( "Browser/View" ) )
04622         variantlist << QString("Browser/View");
04623 
04624       KParts::ReadOnlyPart* part = factory->create<KParts::ReadOnlyPart>(parentWidget, parent, QString(), variantlist);
04625       if ( part ) {
04626         serviceTypes = service->serviceTypes();
04627         serviceName = service->name();
04628         return part;
04629       }
04630     } else {
04631       // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
04632       kWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
04633                       .arg(service->name()).arg(loader.errorString());
04634     }
04635   }
04636   return 0;
04637 }
04638 
04639 KParts::PartManager *KHTMLPart::partManager()
04640 {
04641   if ( !d->m_manager && d->m_view )
04642   {
04643     d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this );
04644     d->m_manager->setObjectName( "khtml part manager" );
04645     d->m_manager->setAllowNestedParts( true );
04646     connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
04647              this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
04648     connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
04649              this, SLOT( slotPartRemoved( KParts::Part * ) ) );
04650   }
04651 
04652   return d->m_manager;
04653 }
04654 
04655 void KHTMLPart::submitFormAgain()
04656 {
04657   disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04658   if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
04659     KHTMLPart::submitForm( d->m_submitForm->submitAction, d->m_submitForm->submitUrl, d->m_submitForm->submitFormData, d->m_submitForm->target, d->m_submitForm->submitContentType, d->m_submitForm->submitBoundary );
04660 
04661   delete d->m_submitForm;
04662   d->m_submitForm = 0;
04663 }
04664 
04665 void KHTMLPart::submitFormProxy( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04666 {
04667   submitForm(action, url, formData, _target, contentType, boundary);
04668 }
04669 
04670 void KHTMLPart::submitForm( const char *action, const QString &url, const QByteArray &formData, const QString &_target, const QString& contentType, const QString& boundary )
04671 {
04672   kDebug(6000) << this << "target=" << _target << "url=" << url;
04673   if (d->m_formNotification == KHTMLPart::Only) {
04674     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04675     return;
04676   } else if (d->m_formNotification == KHTMLPart::Before) {
04677     emit formSubmitNotification(action, url, formData, _target, contentType, boundary);
04678   }
04679 
04680   KUrl u = completeURL( url );
04681 
04682   if ( !u.isValid() )
04683   {
04684     // ### ERROR HANDLING!
04685     return;
04686   }
04687 
04688   // Form security checks
04689   //
04690   /*
04691    * If these form security checks are still in this place in a month or two
04692    * I'm going to simply delete them.
04693    */
04694 
04695   /* This is separate for a reason.  It has to be _before_ all script, etc,
04696    * AND I don't want to break anything that uses checkLinkSecurity() in
04697    * other places.
04698    */
04699 
04700   if (!d->m_submitForm) {
04701     if (u.protocol() != "https" && u.protocol() != "mailto") {
04702       if (d->m_ssl_in_use) {    // Going from SSL -> nonSSL
04703         int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning:  This is a secure form but it is attempting to send your data back unencrypted."
04704                                                                "\nA third party may be able to intercept and view this information."
04705                                                                "\nAre you sure you wish to continue?"),
04706                                                     i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
04707         if (rc == KMessageBox::Cancel)
04708           return;
04709       } else {                  // Going from nonSSL -> nonSSL
04710         KSSLSettings kss(true);
04711         if (kss.warnOnUnencrypted()) {
04712           int rc = KMessageBox::warningContinueCancel(NULL,
04713                                                       i18n("Warning: Your data is about to be transmitted across the network unencrypted."
04714                                                            "\nAre you sure you wish to continue?"),
04715                                                       i18n("Network Transmission"),
04716                                                       KGuiItem(i18n("&Send Unencrypted")),
04717                                                       KStandardGuiItem::cancel(),
04718                                                       "WarnOnUnencryptedForm");
04719           // Move this setting into KSSL instead
04720           QString grpNotifMsgs = QLatin1String("Notification Messages");
04721           KConfigGroup cg( KGlobal::config(), grpNotifMsgs );
04722 
04723           if (!cg.readEntry("WarnOnUnencryptedForm", true)) {
04724             cg.deleteEntry("WarnOnUnencryptedForm");
04725             cg.sync();
04726             kss.setWarnOnUnencrypted(false);
04727             kss.save();
04728           }
04729           if (rc == KMessageBox::Cancel)
04730             return;
04731         }
04732       }
04733     }
04734 
04735     if (u.protocol() == "mailto") {
04736       int rc = KMessageBox::warningContinueCancel(NULL,
04737                                                   i18n("This site is attempting to submit form data via email.\n"
04738                                                        "Do you want to continue?"),
04739                                                   i18n("Network Transmission"),
04740                                                   KGuiItem(i18n("&Send Email")),
04741                                                   KStandardGuiItem::cancel(),
04742                                                   "WarnTriedEmailSubmit");
04743 
04744       if (rc == KMessageBox::Cancel) {
04745         return;
04746       }
04747     }
04748   }
04749 
04750   // End form security checks
04751   //
04752 
04753   QString urlstring = u.url();
04754 
04755   if ( d->isJavaScriptURL(urlstring) ) {
04756     crossFrameExecuteScript( _target, d->codeForJavaScriptURL(urlstring) );
04757     return;
04758   }
04759 
04760   if (!checkLinkSecurity(u,
04761                          ki18n( "<qt>The form will be submitted to <br /><b>%1</b><br />on your local filesystem.<br />Do you want to submit the form?</qt>" ),
04762                          i18n( "Submit" )))
04763     return;
04764 
04765   // OK. We're actually going to submit stuff. Clear any redirections,
04766   // we should win over them
04767   d->clearRedirection();
04768 
04769   KParts::OpenUrlArguments args;
04770 
04771   if (!d->m_referrer.isEmpty())
04772      args.metaData()["referrer"] = d->m_referrer;
04773 
04774   args.metaData().insert("PropagateHttpHeader", "true");
04775   args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
04776   args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
04777   args.metaData().insert("main_frame_request",
04778                          parentPart() == 0 ? "TRUE":"FALSE");
04779   args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
04780   args.metaData().insert("ssl_activate_warnings", "TRUE");
04781 //WABA: When we post a form we should treat it as the main url
04782 //the request should never be considered cross-domain
04783 //args.metaData().insert("cross-domain", toplevelURL().url());
04784   KParts::BrowserArguments browserArgs;
04785   browserArgs.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
04786 
04787   // Handle mailto: forms
04788   if (u.protocol() == "mailto") {
04789       // 1)  Check for attach= and strip it
04790       QString q = u.query().mid(1);
04791       QStringList nvps = q.split("&");
04792       bool triedToAttach = false;
04793 
04794       QStringList::Iterator nvp = nvps.begin();
04795       const QStringList::Iterator nvpEnd = nvps.end();
04796 
04797 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
04798 // remove returns an iterator pointing to the next item
04799 
04800       while (nvp != nvpEnd) {
04801          const QStringList pair = (*nvp).split("=");
04802          if (pair.count() >= 2) {
04803             if (pair.first().toLower() == "attach") {
04804                nvp = nvps.erase(nvp);
04805                triedToAttach = true;
04806             } else {
04807                ++nvp;
04808             }
04809          } else {
04810             ++nvp;
04811          }
04812       }
04813 
04814       if (triedToAttach)
04815          KMessageBox::information(NULL, i18n("This site attempted to attach a file from your computer in the form submission. The attachment was removed for your protection."), i18n("KDE"), "WarnTriedAttach");
04816 
04817       // 2)  Append body=
04818       QString bodyEnc;
04819       if (contentType.toLower() == "multipart/form-data") {
04820          // FIXME: is this correct?  I suspect not
04821          bodyEnc = QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData.data(),
04822                                                            formData.size())));
04823       } else if (contentType.toLower() == "text/plain") {
04824          // Convention seems to be to decode, and s/&/\n/
04825          QString tmpbody = QString::fromLatin1(formData.data(),
04826                                                formData.size());
04827          tmpbody.replace(QRegExp("[&]"), "\n");
04828          tmpbody.replace(QRegExp("[+]"), " ");
04829          tmpbody = KUrl::fromPercentEncoding(tmpbody.toLatin1());  // Decode the rest of it
04830          bodyEnc = QLatin1String( KUrl::toPercentEncoding(tmpbody) );  // Recode for the URL
04831       } else {
04832          bodyEnc = QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData.data(),
04833                                                            formData.size())) );
04834       }
04835 
04836       nvps.append(QString("body=%1").arg(bodyEnc));
04837       q = nvps.join("&");
04838       u.setQuery(q);
04839   }
04840 
04841   if ( strcmp( action, "get" ) == 0 ) {
04842     if (u.protocol() != "mailto")
04843        u.setQuery( QString::fromLatin1( formData.data(), formData.size() ) );
04844     browserArgs.setDoPost( false );
04845   }
04846   else {
04847     browserArgs.postData = formData;
04848     browserArgs.setDoPost( true );
04849 
04850     // construct some user headers if necessary
04851     if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
04852       browserArgs.setContentType( "Content-Type: application/x-www-form-urlencoded" );
04853     else // contentType must be "multipart/form-data"
04854       browserArgs.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
04855   }
04856 
04857   if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
04858     if( d->m_submitForm ) {
04859       kDebug(6000) << "ABORTING!";
04860       return;
04861     }
04862     d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
04863     d->m_submitForm->submitAction = action;
04864     d->m_submitForm->submitUrl = url;
04865     d->m_submitForm->submitFormData = formData;
04866     d->m_submitForm->target = _target;
04867     d->m_submitForm->submitContentType = contentType;
04868     d->m_submitForm->submitBoundary = boundary;
04869     connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
04870   }
04871   else
04872   {
04873     emit d->m_extension->openUrlRequest( u, args, browserArgs );
04874   }
04875 }
04876 
04877 void KHTMLPart::popupMenu( const QString &linkUrl )
04878 {
04879   KUrl popupURL;
04880   KUrl linkKUrl;
04881   KParts::OpenUrlArguments args;
04882   KParts::BrowserArguments browserArgs;
04883   QString referrer;
04884   KParts::BrowserExtension::PopupFlags itemflags=KParts::BrowserExtension::ShowBookmark | KParts::BrowserExtension::ShowReload;
04885 
04886   if ( linkUrl.isEmpty() ) { // click on background
04887     KHTMLPart* khtmlPart = this;
04888     while ( khtmlPart->parentPart() )
04889     {
04890       khtmlPart=khtmlPart->parentPart();
04891     }
04892     popupURL = khtmlPart->url();
04893     referrer = khtmlPart->pageReferrer();
04894     if (hasSelection())
04895       itemflags = KParts::BrowserExtension::ShowTextSelectionItems;
04896     else
04897       itemflags |= KParts::BrowserExtension::ShowNavigationItems;
04898   } else {               // click on link
04899     popupURL = completeURL( linkUrl );
04900     linkKUrl = popupURL;
04901     referrer = this->referrer();
04902     itemflags |= KParts::BrowserExtension::IsLink;
04903 
04904     if (!(d->m_strSelectedURLTarget).isEmpty() &&
04905            (d->m_strSelectedURLTarget.toLower() != "_top") &&
04906            (d->m_strSelectedURLTarget.toLower() != "_self") &&
04907            (d->m_strSelectedURLTarget.toLower() != "_parent")) {
04908       if (d->m_strSelectedURLTarget.toLower() == "_blank")
04909         browserArgs.setForcesNewWindow(true);
04910       else {
04911         KHTMLPart *p = this;
04912         while (p->parentPart())
04913           p = p->parentPart();
04914         if (!p->frameExists(d->m_strSelectedURLTarget))
04915           browserArgs.setForcesNewWindow(true);
04916       }
04917     }
04918   }
04919 
04920   // Danger, Will Robinson. The Popup might stay around for a much
04921   // longer time than KHTMLPart. Deal with it.
04922   KHTMLPopupGUIClient* client = new KHTMLPopupGUIClient( this, linkKUrl );
04923   QPointer<QObject> guard( client );
04924 
04925   QString mimetype = QLatin1String( "text/html" );
04926   args.metaData()["referrer"] = referrer;
04927 
04928   if (!linkUrl.isEmpty())                                // over a link
04929   {
04930     if (popupURL.isLocalFile())                                // safe to do this
04931     {
04932       mimetype = KMimeType::findByUrl(popupURL,0,true,false)->name();
04933     }
04934     else                                                // look at "extension" of link
04935     {
04936       const QString fname(popupURL.fileName(KUrl::ObeyTrailingSlash));
04937       if (!fname.isEmpty() && !popupURL.hasRef() && popupURL.query().isEmpty())
04938       {
04939         KMimeType::Ptr pmt = KMimeType::findByPath(fname,0,true);
04940 
04941         // Further check for mime types guessed from the extension which,
04942         // on a web page, are more likely to be a script delivering content
04943         // of undecidable type. If the mime type from the extension is one
04944         // of these, don't use it.  Retain the original type 'text/html'.
04945         if (pmt->name() != KMimeType::defaultMimeType() &&
04946             !pmt->is("application/x-perl") &&
04947             !pmt->is("application/x-perl-module") &&
04948             !pmt->is("application/x-php") &&
04949             !pmt->is("application/x-python-bytecode") &&
04950             !pmt->is("application/x-python") &&
04951             !pmt->is("application/x-shellscript"))
04952           mimetype = pmt->name();
04953       }
04954     }
04955   }
04956 
04957   args.setMimeType(mimetype);
04958 
04959   emit d->m_extension->popupMenu( QCursor::pos(), popupURL, S_IFREG /*always a file*/,
04960                                   args, browserArgs, itemflags,
04961                                   client->actionGroups() );
04962 
04963   if ( !guard.isNull() ) {
04964      delete client;
04965      emit popupMenu(linkUrl, QCursor::pos());
04966      d->m_strSelectedURL.clear();
04967      d->m_strSelectedURLTarget.clear();
04968   }
04969 }
04970 
04971 void KHTMLPart::slotParentCompleted()
04972 {
04973   //kDebug(6050) << this;
04974   if ( !d->m_redirectURL.isEmpty() && !d->m_redirectionTimer.isActive() )
04975   {
04976     //kDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL;
04977     d->m_redirectionTimer.setSingleShot( true );
04978     d->m_redirectionTimer.start( qMax(0, 1000 * d->m_delayRedirect) );
04979   }
04980 }
04981 
04982 void KHTMLPart::slotChildStarted( KIO::Job *job )
04983 {
04984   khtml::ChildFrame *child = frame( sender() );
04985 
04986   assert( child );
04987 
04988   child->m_bCompleted = false;
04989 
04990   if ( d->m_bComplete )
04991   {
04992 #if 0
04993     // WABA: Looks like this belongs somewhere else
04994     if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
04995     {
04996       emit d->m_extension->openURLNotify();
04997     }
04998 #endif
04999     d->m_bComplete = false;
05000     emit started( job );
05001   }
05002 }
05003 
05004 void KHTMLPart::slotChildCompleted()
05005 {
05006   slotChildCompleted( false );
05007 }
05008 
05009 void KHTMLPart::slotChildCompleted( bool pendingAction )
05010 {
05011   khtml::ChildFrame *child = frame( sender() );
05012 
05013   if ( child ) {
05014     kDebug(6031) << this << "child=" << child << "m_partContainerElement=" << child->m_partContainerElement;
05015     child->m_bCompleted = true;
05016     child->m_bPendingRedirection = pendingAction;
05017     child->m_args = KParts::OpenUrlArguments();
05018     child->m_browserArgs = KParts::BrowserArguments();
05019     // dispatch load event. We don't do that for KHTMLPart's since their internal
05020     // load will be forwarded inside NodeImpl::dispatchWindowEvent
05021     if (!qobject_cast<KHTMLPart*>(child->m_part))
05022         QTimer::singleShot(0, child->m_partContainerElement.data(), SLOT(slotEmitLoadEvent()));
05023   }
05024   checkCompleted();
05025 }
05026 
05027 void KHTMLPart::slotChildDocCreated()
05028 {
05029   // Set domain to the frameset's domain
05030   // This must only be done when loading the frameset initially (#22039),
05031   // not when following a link in a frame (#44162).
05032   if (KHTMLPart* htmlFrame = qobject_cast<KHTMLPart*>(sender()))
05033       d->propagateInitialDomainAndBaseTo(htmlFrame);
05034 
05035   // So it only happens once
05036   disconnect( sender(), SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
05037 }
05038 
05039 void KHTMLPartPrivate::propagateInitialDomainAndBaseTo(KHTMLPart* kid)
05040 {
05041     // This method is used to propagate our domain and base information for
05042     // child frames, to provide them for about: or JavaScript: URLs 
05043     if ( m_doc && kid->d->m_doc ) {
05044         DocumentImpl* kidDoc = kid->d->m_doc;
05045         if ( kidDoc->origin()->isEmpty() ) {
05046             kidDoc->setOrigin ( m_doc->origin() );
05047             kidDoc->setBaseURL( m_doc->baseURL() );
05048         }
05049     }
05050 }
05051 
05052 void KHTMLPart::slotChildURLRequest( const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs )
05053 {
05054   khtml::ChildFrame *child = frame( sender()->parent() );
05055   KHTMLPart *callingHtmlPart = const_cast<KHTMLPart *>(dynamic_cast<const KHTMLPart *>(sender()->parent()));
05056 
05057   // TODO: handle child target correctly! currently the script are always executed for the parent
05058   QString urlStr = url.url();
05059   if ( d->isJavaScriptURL(urlStr) ) {
05060       executeScript( DOM::Node(), d->codeForJavaScriptURL(urlStr) );
05061       return;
05062   }
05063 
05064   QString frameName = browserArgs.frameName.toLower();
05065   if ( !frameName.isEmpty() ) {
05066     if ( frameName == QLatin1String( "_top" ) )
05067     {
05068       emit d->m_extension->openUrlRequest( url, args, browserArgs );
05069       return;
05070     }
05071     else if ( frameName == QLatin1String( "_blank" ) )
05072     {
05073       emit d->m_extension->createNewWindow( url, args, browserArgs );
05074       return;
05075     }
05076     else if ( frameName == QLatin1String( "_parent" ) )
05077     {
05078       KParts::BrowserArguments newBrowserArgs( browserArgs );
05079       newBrowserArgs.frameName.clear();
05080       emit d->m_extension->openUrlRequest( url, args, newBrowserArgs );
05081       return;
05082     }
05083     else if ( frameName != QLatin1String( "_self" ) )
05084     {
05085       khtml::ChildFrame *_frame = recursiveFrameRequest( callingHtmlPart, url, args, browserArgs );
05086 
05087       if ( !_frame )
05088       {
05089         emit d->m_extension->openUrlRequest( url, args, browserArgs );
05090         return;
05091       }
05092 
05093       child = _frame;
05094     }
05095   }
05096 
05097   if ( child && child->m_type != khtml::ChildFrame::Object ) {
05098       // Inform someone that we are about to show something else.
05099       child->m_bNotify = true;
05100       requestObject( child, url, args, browserArgs );
05101   }  else if ( frameName== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
05102   {
05103       KParts::BrowserArguments newBrowserArgs( browserArgs );
05104       newBrowserArgs.frameName.clear();
05105       emit d->m_extension->openUrlRequest( url, args, newBrowserArgs );
05106   }
05107 }
05108 
05109 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart * )
05110 {
05111   emit d->m_extension->requestFocus(this);
05112 }
05113 
05114 khtml::ChildFrame *KHTMLPart::frame( const QObject *obj )
05115 {
05116     assert( obj->inherits( "KParts::ReadOnlyPart" ) );
05117     const KParts::ReadOnlyPart* const part = static_cast<const KParts::ReadOnlyPart *>( obj );
05118 
05119     FrameIt it = d->m_frames.begin();
05120     const FrameIt end = d->m_frames.end();
05121     for (; it != end; ++it ) {
05122         if ((*it)->m_part.data() == part )
05123             return *it;
05124     }
05125 
05126     FrameIt oi = d->m_objects.begin();
05127     const FrameIt oiEnd = d->m_objects.end();
05128     for (; oi != oiEnd; ++oi ) {
05129         if ((*oi)->m_part.data() == part)
05130             return *oi;
05131     }
05132 
05133     return 0L;
05134 }
05135 
05136 //#define DEBUG_FINDFRAME
05137 
05138 bool KHTMLPart::checkFrameAccess(KHTMLPart *callingHtmlPart)
05139 {
05140   if (callingHtmlPart == this)
05141     return true; // trivial
05142 
05143   if (!xmlDocImpl()) {
05144 #ifdef DEBUG_FINDFRAME
05145     kDebug(6050) << "Empty part" << this << "URL = " << url();
05146 #endif
05147     return false; // we are empty?
05148   }
05149   
05150   // now compare the domains
05151   if (callingHtmlPart && callingHtmlPart->xmlDocImpl() && xmlDocImpl())  {
05152     khtml::SecurityOrigin* actDomain = callingHtmlPart->xmlDocImpl()->origin();
05153     khtml::SecurityOrigin* destDomain = xmlDocImpl()->origin();
05154 
05155     if (actDomain->canAccess(destDomain))
05156       return true;
05157   }
05158 #ifdef DEBUG_FINDFRAME
05159   else
05160   {
05161     kDebug(6050) << "Unknown part/domain" << callingHtmlPart << "tries to access part" << this;
05162   }
05163 #endif
05164   return false;
05165 }
05166 
05167 KHTMLPart *
05168 KHTMLPart::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &f, khtml::ChildFrame **childFrame )
05169 {
05170     return d->findFrameParent(callingPart, f, childFrame, false);
05171 }
05172 
05173 KHTMLPart* KHTMLPartPrivate::findFrameParent(KParts::ReadOnlyPart* callingPart, 
05174                                              const QString& f, khtml::ChildFrame **childFrame, bool checkForNavigation)
05175 {
05176 #ifdef DEBUG_FINDFRAME
05177     kDebug(6050) << q << "URL =" << q->url() << "name =" << q->objectName() << "findFrameParent(" << f << ")";
05178 #endif
05179     // Check access
05180     KHTMLPart* const callingHtmlPart = dynamic_cast<KHTMLPart *>(callingPart);
05181 
05182     if (!checkForNavigation && !q->checkFrameAccess(callingHtmlPart))
05183         return 0;
05184 
05185     if (!childFrame && !q->parentPart() && (q->objectName() == f)) {
05186         if (!checkForNavigation || callingHtmlPart->d->canNavigate(q))
05187             return q;
05188     }
05189 
05190     FrameIt it = m_frames.find( f );
05191     const FrameIt end = m_frames.end();
05192     if ( it != end )
05193     {
05194 #ifdef DEBUG_FINDFRAME
05195         kDebug(6050) << "FOUND!";
05196 #endif
05197         if (!checkForNavigation || callingHtmlPart->d->canNavigate((*it)->m_part.data())) {
05198             if (childFrame)
05199                 *childFrame = *it;
05200             return q;
05201         }
05202     }
05203 
05204     it = m_frames.begin();
05205     for (; it != end; ++it )
05206     {
05207         if ( KHTMLPart* p = qobject_cast<KHTMLPart*>((*it)->m_part.data()) )
05208         {
05209             KHTMLPart* const frameParent = p->d->findFrameParent(callingPart, f, childFrame, checkForNavigation);
05210             if (frameParent)
05211                 return frameParent;
05212         }
05213     }
05214     return 0;
05215 }
05216 
05217 KHTMLPart* KHTMLPartPrivate::top()
05218 {
05219     KHTMLPart* t = q;
05220     while (t->parentPart())
05221         t = t->parentPart();
05222     return t;
05223 }
05224 
05225 bool KHTMLPartPrivate::canNavigate(KParts::ReadOnlyPart* bCand)
05226 {
05227     KHTMLPart* b = qobject_cast<KHTMLPart*>(bCand);
05228     assert(b);
05229 
05230     // HTML5 gives conditions for this (a) being able to navigate b
05231     
05232     // 1) Same domain
05233     if (q->checkFrameAccess(b))
05234         return true;
05235         
05236     // 2) A is nested, with B its top
05237     if (q->parentPart() && top() == b)
05238         return true;
05239         
05240     // 3) B is 'auxilary' -- window.open with opener, 
05241     // and A can navigate B's opener
05242     if (b->opener() && canNavigate(b->opener()))
05243         return true;
05244         
05245     // 4) B is not top-level, but an ancestor of it has same origin as A
05246     for (KHTMLPart* anc = b->parentPart(); anc; anc = anc->parentPart()) {
05247         if (anc->checkFrameAccess(q))
05248             return true;
05249     }
05250     
05251     return false;
05252 }
05253 
05254 KHTMLPart *KHTMLPart::findFrame( const QString &f )
05255 {
05256   khtml::ChildFrame *childFrame;
05257   KHTMLPart *parentFrame = findFrameParent(this, f, &childFrame);
05258   if (parentFrame)
05259      return qobject_cast<KHTMLPart*>(childFrame->m_part.data());
05260 
05261   return 0;
05262 }
05263 
05264 KParts::ReadOnlyPart *KHTMLPart::findFramePart(const QString &f)
05265 {
05266   khtml::ChildFrame *childFrame;
05267   return findFrameParent(this, f, &childFrame) ? childFrame->m_part.data() : 0L;
05268 }
05269 
05270 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
05271 {
05272   KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
05273   // Find active part in our frame manager, in case we are a frameset
05274   // and keep doing that (in case of nested framesets).
05275   // Just realized we could also do this recursively, calling part->currentFrame()...
05276   while ( part && part->inherits("KHTMLPart") &&
05277           static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
05278     KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
05279     part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
05280     if ( !part ) return frameset;
05281   }
05282   return part;
05283 }
05284 
05285 bool KHTMLPart::frameExists( const QString &frameName )
05286 {
05287   FrameIt it = d->m_frames.find( frameName );
05288   if ( it == d->m_frames.end() )
05289     return false;
05290 
05291   // WABA: We only return true if the child actually has a frame
05292   // set. Otherwise we might find our preloaded-selve.
05293   // This happens when we restore the frameset.
05294   return (!(*it)->m_partContainerElement.isNull());
05295 }
05296 
05297 void KHTMLPartPrivate::renameFrameForContainer(DOM::HTMLPartContainerElementImpl* cont,
05298                                                const QString& newName)
05299 {
05300     for (int i = 0; i < m_frames.size(); ++i) {
05301         khtml::ChildFrame* f = m_frames[i];
05302         if (f->m_partContainerElement.data() == cont)
05303             f->m_name = newName;
05304     }
05305 }
05306 
05307 KJSProxy *KHTMLPart::framejScript(KParts::ReadOnlyPart *framePart)
05308 {
05309   KHTMLPart* const kp = qobject_cast<KHTMLPart*>(framePart);
05310   if (kp)
05311     return kp->jScript();
05312 
05313   FrameIt it = d->m_frames.begin();
05314   const FrameIt itEnd = d->m_frames.end();
05315 
05316   for (; it != itEnd; ++it) {
05317     khtml::ChildFrame* frame = *it;
05318     if (framePart == frame->m_part.data()) {
05319       if (!frame->m_jscript)
05320         frame->m_jscript = new KJSProxy(frame);
05321       return frame->m_jscript;
05322     }
05323   }
05324   return 0L;
05325 }
05326 
05327 KHTMLPart *KHTMLPart::parentPart()
05328 {
05329   return qobject_cast<KHTMLPart*>( parent() );
05330 }
05331 
05332 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( KHTMLPart *callingHtmlPart, const KUrl &url,
05333                                                      const KParts::OpenUrlArguments &args,
05334                                                      const KParts::BrowserArguments &browserArgs, bool callParent )
05335 {
05336 #ifdef DEBUG_FINDFRAME
05337   kDebug( 6050 ) << this << "frame = " << args.frameName << "url = " << url;
05338 #endif
05339   khtml::ChildFrame *childFrame;
05340   KHTMLPart *childPart = findFrameParent(callingHtmlPart, browserArgs.frameName, &childFrame);
05341   if (childPart)
05342   {
05343      if (childPart == this)
05344         return childFrame;
05345 
05346      childPart->requestObject( childFrame, url, args, browserArgs );
05347      return 0;
05348   }
05349 
05350   if ( parentPart() && callParent )
05351   {
05352      khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( callingHtmlPart, url, args, browserArgs, callParent );
05353 
05354      if ( res )
05355        parentPart()->requestObject( res, url, args, browserArgs );
05356   }
05357 
05358   return 0L;
05359 }
05360 
05361 #ifdef DEBUG_SAVESTATE
05362 static int s_saveStateIndentLevel = 0;
05363 #endif
05364 
05365 void KHTMLPart::saveState( QDataStream &stream )
05366 {
05367 #ifdef DEBUG_SAVESTATE
05368   QString indent= QString().leftJustified( s_saveStateIndentLevel * 4, ' ' );
05369   const int indentLevel = s_saveStateIndentLevel++;
05370   kDebug( 6050 ) << indent << "saveState this=" << this << " '" << objectName() << "' saving URL " << url().url();
05371 #endif
05372 
05373   stream << url() << (qint32)d->m_view->contentsX() << (qint32)d->m_view->contentsY()
05374          << (qint32) d->m_view->contentsWidth() << (qint32) d->m_view->contentsHeight() << (qint32) d->m_view->marginWidth() << (qint32) d->m_view->marginHeight();
05375 
05376   // save link cursor position
05377   int focusNodeNumber;
05378   if (!d->m_focusNodeRestored)
05379       focusNodeNumber = d->m_focusNodeNumber;
05380   else if (d->m_doc && d->m_doc->focusNode())
05381       focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
05382   else
05383       focusNodeNumber = -1;
05384   stream << focusNodeNumber;
05385 
05386   // Save the doc's cache id.
05387   stream << d->m_cacheId;
05388 
05389   // Save the state of the document (Most notably the state of any forms)
05390   QStringList docState;
05391   if (d->m_doc)
05392   {
05393      docState = d->m_doc->docState();
05394   }
05395   stream << d->m_encoding << d->m_sheetUsed << docState;
05396 
05397   stream << d->m_zoomFactor;
05398   stream << d->m_fontScaleFactor;
05399 
05400   stream << d->m_httpHeaders;
05401   stream << d->m_pageServices;
05402   stream << d->m_pageReferrer;
05403 
05404   // Save ssl data
05405   stream << d->m_ssl_in_use
05406          << d->m_ssl_peer_chain
05407          << d->m_ssl_peer_ip
05408          << d->m_ssl_cipher
05409          << d->m_ssl_protocol_version
05410          << d->m_ssl_cipher_used_bits
05411          << d->m_ssl_cipher_bits
05412          << d->m_ssl_cert_errors
05413          << d->m_ssl_parent_ip
05414          << d->m_ssl_parent_cert;
05415 
05416 
05417   QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
05418   KUrl::List frameURLLst;
05419   QList<QByteArray> frameStateBufferLst;
05420   QList<int> frameTypeLst;
05421 
05422   ConstFrameIt it = d->m_frames.constBegin();
05423   const ConstFrameIt end = d->m_frames.constEnd();
05424   for (; it != end; ++it )
05425   {
05426     if ( !(*it)->m_part )
05427        continue;
05428 
05429     frameNameLst << (*it)->m_name;
05430     frameServiceTypeLst << (*it)->m_serviceType;
05431     frameServiceNameLst << (*it)->m_serviceName;
05432     frameURLLst << (*it)->m_part.data()->url();
05433 
05434     QByteArray state;
05435     QDataStream frameStream( &state, QIODevice::WriteOnly );
05436 
05437     if ( (*it)->m_extension )
05438       (*it)->m_extension.data()->saveState( frameStream );
05439 
05440     frameStateBufferLst << state;
05441 
05442     frameTypeLst << int( (*it)->m_type );
05443   }
05444 
05445   // Save frame data
05446   stream << (quint32) frameNameLst.count();
05447   stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst << frameTypeLst;
05448 #ifdef DEBUG_SAVESTATE
05449   s_saveStateIndentLevel = indentLevel;
05450 #endif
05451 }
05452 
05453 void KHTMLPart::restoreState( QDataStream &stream )
05454 {
05455   KUrl u;
05456   qint32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
05457   quint32 frameCount;
05458   QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
05459   QList<int> frameTypes;
05460   KUrl::List frameURLs;
05461   QList<QByteArray> frameStateBuffers;
05462   QList<int> fSizes;
05463   QString encoding, sheetUsed;
05464   long old_cacheId = d->m_cacheId;
05465 
05466   stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
05467 
05468   d->m_view->setMarginWidth( mWidth );
05469   d->m_view->setMarginHeight( mHeight );
05470 
05471   // restore link cursor position
05472   // nth node is active. value is set in checkCompleted()
05473   stream >> d->m_focusNodeNumber;
05474   d->m_focusNodeRestored = false;
05475 
05476   stream >> d->m_cacheId;
05477 
05478   stream >> encoding >> sheetUsed >> docState;
05479 
05480   d->m_encoding = encoding;
05481   d->m_sheetUsed = sheetUsed;
05482 
05483   int zoomFactor;
05484   stream >> zoomFactor;
05485   setZoomFactor(zoomFactor);
05486 
05487   int fontScaleFactor;
05488   stream >> fontScaleFactor;
05489   setFontScaleFactor(fontScaleFactor);
05490 
05491   stream >> d->m_httpHeaders;
05492   stream >> d->m_pageServices;
05493   stream >> d->m_pageReferrer;
05494 
05495   // Restore ssl data
05496   stream >> d->m_ssl_in_use
05497          >> d->m_ssl_peer_chain
05498          >> d->m_ssl_peer_ip
05499          >> d->m_ssl_cipher
05500          >> d->m_ssl_protocol_version
05501          >> d->m_ssl_cipher_used_bits
05502          >> d->m_ssl_cipher_bits
05503          >> d->m_ssl_cert_errors
05504          >> d->m_ssl_parent_ip
05505          >> d->m_ssl_parent_cert;
05506 
05507   setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
05508 
05509   stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
05510          >> frameURLs >> frameStateBuffers >> frameTypes;
05511 
05512   d->m_bComplete = false;
05513   d->m_bLoadEventEmitted = false;
05514 
05515 //   kDebug( 6050 ) << "docState.count() = " << docState.count();
05516 //   kDebug( 6050 ) << "m_url " << url().url() << " <-> " << u.url();
05517 //   kDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount;
05518 
05519   if (d->m_cacheId == old_cacheId && signed(frameCount) == d->m_frames.count())
05520   {
05521     // Partial restore
05522     d->m_redirectionTimer.stop();
05523 
05524     FrameIt fIt = d->m_frames.begin();
05525     const FrameIt fEnd = d->m_frames.end();
05526 
05527     for (; fIt != fEnd; ++fIt )
05528         (*fIt)->m_bCompleted = false;
05529 
05530     fIt = d->m_frames.begin();
05531 
05532     QStringList::ConstIterator fNameIt = frameNames.constBegin();
05533     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.constBegin();
05534     QStringList::ConstIterator fServiceNameIt = frameServiceNames.constBegin();
05535     KUrl::List::ConstIterator fURLIt = frameURLs.constBegin();
05536     QList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.constBegin();
05537     QList<int>::ConstIterator fFrameTypeIt = frameTypes.constBegin();
05538 
05539     for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt, ++fFrameTypeIt )
05540     {
05541       khtml::ChildFrame* const child = *fIt;
05542 
05543 //      kDebug( 6050 ) <<  *fNameIt  << " ---- " <<  *fServiceTypeIt;
05544 
05545       if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
05546       {
05547         child->m_bPreloaded = true;
05548         child->m_name = *fNameIt;
05549         child->m_serviceName = *fServiceNameIt;
05550         child->m_type = static_cast<khtml::ChildFrame::Type>(*fFrameTypeIt);
05551         processObjectRequest( child, *fURLIt, *fServiceTypeIt );
05552       }
05553       if ( child->m_part )
05554       {
05555         child->m_bCompleted = false;
05556         if ( child->m_extension && !(*fBufferIt).isEmpty() )
05557         {
05558           QDataStream frameStream( *fBufferIt );
05559           child->m_extension.data()->restoreState( frameStream );
05560         }
05561         else
05562           child->m_part.data()->openUrl( *fURLIt );
05563       }
05564     }
05565 
05566     KParts::OpenUrlArguments args( arguments() );
05567     args.setXOffset(xOffset);
05568     args.setYOffset(yOffset);
05569     setArguments(args);
05570 
05571     KParts::BrowserArguments browserArgs( d->m_extension->browserArguments() );
05572     browserArgs.docState = docState;
05573     d->m_extension->setBrowserArguments(browserArgs);
05574 
05575     d->m_view->resizeContents( wContents, hContents );
05576     d->m_view->setContentsPos( xOffset, yOffset );
05577 
05578     setUrl(u);
05579   }
05580   else
05581   {
05582     // Full restore.
05583     closeUrl();
05584     // We must force a clear because we want to be sure to delete all
05585     // frames.
05586     d->m_bCleared = false;
05587     clear();
05588     d->m_encoding = encoding;
05589     d->m_sheetUsed = sheetUsed;
05590 
05591     QStringList::ConstIterator fNameIt = frameNames.constBegin();
05592     const QStringList::ConstIterator fNameEnd = frameNames.constEnd();
05593 
05594     QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.constBegin();
05595     QStringList::ConstIterator fServiceNameIt = frameServiceNames.constBegin();
05596     KUrl::List::ConstIterator fURLIt = frameURLs.constBegin();
05597     QList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.constBegin();
05598     QList<int>::ConstIterator fFrameTypeIt = frameTypes.constBegin();
05599 
05600     for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt, ++fFrameTypeIt )
05601     {
05602       khtml::ChildFrame* const newChild = new khtml::ChildFrame;
05603       newChild->m_bPreloaded = true;
05604       newChild->m_name = *fNameIt;
05605       newChild->m_serviceName = *fServiceNameIt;
05606       newChild->m_type = static_cast<khtml::ChildFrame::Type>(*fFrameTypeIt);
05607 
05608 //      kDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt;
05609 
05610       const FrameIt childFrame = d->m_frames.insert( d->m_frames.end(), newChild );
05611 
05612       processObjectRequest( *childFrame, *fURLIt, *fServiceTypeIt );
05613 
05614       (*childFrame)->m_bPreloaded = true;
05615 
05616       if ( (*childFrame)->m_part )
05617       {
05618         if ( (*childFrame)->m_extension && !(*fBufferIt).isEmpty() )
05619         {
05620           QDataStream frameStream( *fBufferIt );
05621           (*childFrame)->m_extension.data()->restoreState( frameStream );
05622         }
05623         else
05624           (*childFrame)->m_part.data()->openUrl( *fURLIt );
05625       }
05626     }
05627 
05628     KParts::OpenUrlArguments args( arguments() );
05629     args.setXOffset(xOffset);
05630     args.setYOffset(yOffset);
05631     setArguments(args);
05632 
05633     KParts::BrowserArguments browserArgs( d->m_extension->browserArguments() );
05634     browserArgs.docState = docState;
05635     d->m_extension->setBrowserArguments(browserArgs);
05636 
05637     if (!KHTMLPageCache::self()->isComplete(d->m_cacheId))
05638     {
05639        d->m_restored = true;
05640        openUrl( u );
05641        d->m_restored = false;
05642     }
05643     else
05644     {
05645        restoreURL( u );
05646     }
05647   }
05648 
05649 }
05650 
05651 void KHTMLPart::show()
05652 {
05653   if ( widget() )
05654     widget()->show();
05655 }
05656 
05657 void KHTMLPart::hide()
05658 {
05659   if ( widget() )
05660     widget()->hide();
05661 }
05662 
05663 DOM::Node KHTMLPart::nodeUnderMouse() const
05664 {
05665     return d->m_view->nodeUnderMouse();
05666 }
05667 
05668 DOM::Node KHTMLPart::nonSharedNodeUnderMouse() const
05669 {
05670     return d->m_view->nonSharedNodeUnderMouse();
05671 }
05672 
05673 void KHTMLPart::emitSelectionChanged()
05674 {
05675     // Don't emit signals about our selection if this is a frameset;
05676     // the active frame has the selection (#187403)
05677     if (!d->m_activeFrame)
05678     {
05679         emit d->m_extension->enableAction( "copy", hasSelection() );
05680         emit d->m_extension->selectionInfo( selectedText() );
05681         emit selectionChanged();
05682     }
05683 }
05684 
05685 int KHTMLPart::zoomFactor() const
05686 {
05687   return d->m_zoomFactor;
05688 }
05689 
05690 // ### make the list configurable ?
05691 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
05692 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
05693 static const int minZoom = 20;
05694 static const int maxZoom = 300;
05695 
05696 // My idea of useful stepping ;-) (LS)
05697 extern const int KDE_NO_EXPORT fastZoomSizes[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
05698 extern const int KDE_NO_EXPORT fastZoomSizeCount = sizeof fastZoomSizes / sizeof fastZoomSizes[0];
05699 
05700 void KHTMLPart::slotIncZoom()
05701 {
05702   zoomIn(zoomSizes, zoomSizeCount);
05703 }
05704 
05705 void KHTMLPart::slotDecZoom()
05706 {
05707   zoomOut(zoomSizes, zoomSizeCount);
05708 }
05709 
05710 void KHTMLPart::slotIncZoomFast()
05711 {
05712   zoomIn(fastZoomSizes, fastZoomSizeCount);
05713 }
05714 
05715 void KHTMLPart::slotDecZoomFast()
05716 {
05717   zoomOut(fastZoomSizes, fastZoomSizeCount);
05718 }
05719 
05720 void KHTMLPart::zoomIn(const int stepping[], int count)
05721 {
05722   int zoomFactor = d->m_zoomFactor;
05723 
05724   if (zoomFactor < maxZoom) {
05725     // find the entry nearest to the given zoomsizes
05726     for (int i = 0; i < count; ++i)
05727       if (stepping[i] > zoomFactor) {
05728         zoomFactor = stepping[i];
05729         break;
05730       }
05731     setZoomFactor(zoomFactor);
05732   }
05733 }
05734 
05735 void KHTMLPart::zoomOut(const int stepping[], int count)
05736 {
05737     int zoomFactor = d->m_zoomFactor;
05738     if (zoomFactor > minZoom) {
05739       // find the entry nearest to the given zoomsizes
05740       for (int i = count-1; i >= 0; --i)
05741         if (stepping[i] < zoomFactor) {
05742           zoomFactor = stepping[i];
05743           break;
05744         }
05745       setZoomFactor(zoomFactor);
05746     }
05747 }
05748 
05749 void KHTMLPart::setZoomFactor (int percent)
05750 {
05751   // ### zooming under 100% is majorly botched,
05752   //     so disable that for now.
05753   if (percent < 100) percent = 100;
05754   // ### if (percent < minZoom) percent = minZoom;
05755 
05756   if (percent > maxZoom) percent = maxZoom;
05757   if (d->m_zoomFactor == percent) return;
05758   d->m_zoomFactor = percent;
05759 
05760   updateZoomFactor();
05761 }
05762 
05763 
05764 void KHTMLPart::updateZoomFactor ()
05765 {
05766   if(d->m_view) {
05767     QApplication::setOverrideCursor( Qt::WaitCursor );
05768     d->m_view->setZoomLevel( d->m_zoomFactor );
05769     QApplication::restoreOverrideCursor();
05770   }
05771 
05772   ConstFrameIt it = d->m_frames.constBegin();
05773   const ConstFrameIt end = d->m_frames.constEnd();
05774   for (; it != end; ++it ) {
05775       if ( KHTMLPart* p = qobject_cast<KHTMLPart*>((*it)->m_part.data()) )
05776           p->setZoomFactor(d->m_zoomFactor);
05777   }
05778 
05779   if ( d->m_guiProfile == BrowserViewGUI ) {
05780       d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
05781       d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
05782   }
05783 }
05784 
05785 void KHTMLPart::slotIncFontSize()
05786 {
05787   incFontSize(zoomSizes, zoomSizeCount);
05788 }
05789 
05790 void KHTMLPart::slotDecFontSize()
05791 {
05792   decFontSize(zoomSizes, zoomSizeCount);
05793 }
05794 
05795 void KHTMLPart::slotIncFontSizeFast()
05796 {
05797   incFontSize(fastZoomSizes, fastZoomSizeCount);
05798 }
05799 
05800 void KHTMLPart::slotDecFontSizeFast()
05801 {
05802   decFontSize(fastZoomSizes, fastZoomSizeCount);
05803 }
05804 
05805 void KHTMLPart::incFontSize(const int stepping[], int count)
05806 {
05807   int zoomFactor = d->m_fontScaleFactor;
05808 
05809   if (zoomFactor < maxZoom) {
05810     // find the entry nearest to the given zoomsizes
05811     for (int i = 0; i < count; ++i)
05812       if (stepping[i] > zoomFactor) {
05813         zoomFactor = stepping[i];
05814         break;
05815       }
05816     setFontScaleFactor(zoomFactor);
05817   }
05818 }
05819 
05820 void KHTMLPart::decFontSize(const int stepping[], int count)
05821 {
05822     int zoomFactor = d->m_fontScaleFactor;
05823     if (zoomFactor > minZoom) {
05824       // find the entry nearest to the given zoomsizes
05825       for (int i = count-1; i >= 0; --i)
05826         if (stepping[i] < zoomFactor) {
05827           zoomFactor = stepping[i];
05828           break;
05829         }
05830       setFontScaleFactor(zoomFactor);
05831     }
05832 }
05833 
05834 void KHTMLPart::setFontScaleFactor(int percent)
05835 {
05836   if (percent < minZoom) percent = minZoom;
05837   if (percent > maxZoom) percent = maxZoom;
05838   if (d->m_fontScaleFactor == percent) return;
05839   d->m_fontScaleFactor = percent;
05840 
05841   if (d->m_view && d->m_doc) {
05842     QApplication::setOverrideCursor( Qt::WaitCursor );
05843     if (d->m_doc->styleSelector())
05844       d->m_doc->styleSelector()->computeFontSizes(d->m_doc->logicalDpiY(), d->m_fontScaleFactor);
05845     d->m_doc->recalcStyle( NodeImpl::Force );
05846     QApplication::restoreOverrideCursor();
05847   }
05848 
05849   ConstFrameIt it = d->m_frames.constBegin();
05850   const ConstFrameIt end = d->m_frames.constEnd();
05851   for (; it != end; ++it ) {
05852     if ( KHTMLPart* p = qobject_cast<KHTMLPart*>((*it)->m_part.data()) )
05853       p->setFontScaleFactor(d->m_fontScaleFactor);
05854   }
05855 }
05856 
05857 int KHTMLPart::fontScaleFactor() const
05858 {
05859   return d->m_fontScaleFactor;
05860 }
05861 
05862 void KHTMLPart::slotZoomView( int delta )
05863 {
05864   if ( delta < 0 )
05865     slotIncZoom();
05866   else
05867     slotDecZoom();
05868 }
05869 
05870 void KHTMLPart::setStatusBarText( const QString& text, StatusBarPriority p)
05871 {
05872   if (!d->m_statusMessagesEnabled)
05873     return;
05874 
05875   d->m_statusBarText[p] = text;
05876 
05877   // shift handling ?
05878   QString tobe = d->m_statusBarText[BarHoverText];
05879   if (tobe.isEmpty())
05880     tobe = d->m_statusBarText[BarOverrideText];
05881   if (tobe.isEmpty()) {
05882     tobe = d->m_statusBarText[BarDefaultText];
05883     if (!tobe.isEmpty() && d->m_jobspeed)
05884       tobe += " ";
05885     if (d->m_jobspeed)
05886       tobe += i18n( "(%1/s)" ,  KIO::convertSize( d->m_jobspeed ) );
05887   }
05888   tobe = "<qt>"+tobe;
05889 
05890   emit ReadOnlyPart::setStatusBarText(tobe);
05891 }
05892 
05893 
05894 void KHTMLPart::setJSStatusBarText( const QString &text )
05895 {
05896   setStatusBarText(text, BarOverrideText);
05897 }
05898 
05899 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
05900 {
05901   setStatusBarText(text, BarDefaultText);
05902 }
05903 
05904 QString KHTMLPart::jsStatusBarText() const
05905 {
05906     return d->m_statusBarText[BarOverrideText];
05907 }
05908 
05909 QString KHTMLPart::jsDefaultStatusBarText() const
05910 {
05911    return d->m_statusBarText[BarDefaultText];
05912 }
05913 
05914 QString KHTMLPart::referrer() const
05915 {
05916    return d->m_referrer;
05917 }
05918 
05919 QString KHTMLPart::pageReferrer() const
05920 {
05921    KUrl referrerURL = KUrl( d->m_pageReferrer );
05922    if (referrerURL.isValid())
05923    {
05924       QString protocol = referrerURL.protocol();
05925 
05926       if ((protocol == "http") ||
05927          ((protocol == "https") && (url().protocol() == "https")))
05928       {
05929           referrerURL.setRef(QString());
05930           referrerURL.setUser(QString());
05931           referrerURL.setPass(QString());
05932           return referrerURL.url();
05933       }
05934    }
05935 
05936    return QString();
05937 }
05938 
05939 
05940 QString KHTMLPart::lastModified() const
05941 {
05942   if ( d->m_lastModified.isEmpty() && url().isLocalFile() ) {
05943     // Local file: set last-modified from the file's mtime.
05944     // Done on demand to save time when this isn't needed - but can lead
05945     // to slightly wrong results if updating the file on disk w/o reloading.
05946     QDateTime lastModif = QFileInfo( url().toLocalFile() ).lastModified();
05947     d->m_lastModified = lastModif.toString( Qt::LocalDate );
05948   }
05949   //kDebug(6050) << d->m_lastModified;
05950   return d->m_lastModified;
05951 }
05952 
05953 void KHTMLPart::slotLoadImages()
05954 {
05955     if (d->m_doc )
05956         d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
05957 
05958     ConstFrameIt it = d->m_frames.constBegin();
05959     const ConstFrameIt end = d->m_frames.constEnd();
05960     for (; it != end; ++it ) {
05961         if ( KHTMLPart* p = qobject_cast<KHTMLPart*>((*it)->m_part.data()) )
05962             p->slotLoadImages();
05963     }
05964 }
05965 
05966 void KHTMLPart::reparseConfiguration()
05967 {
05968   KHTMLSettings *settings = KHTMLGlobal::defaultHTMLSettings();
05969   settings->init();
05970 
05971   setAutoloadImages( settings->autoLoadImages() );
05972   if (d->m_doc)
05973      d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
05974 
05975   d->m_bOpenMiddleClick = settings->isOpenMiddleClickEnabled();
05976   d->m_bJScriptEnabled = settings->isJavaScriptEnabled(url().host());
05977   setDebugScript( settings->isJavaScriptDebugEnabled() );
05978   d->m_bJavaEnabled = settings->isJavaEnabled(url().host());
05979   d->m_bPluginsEnabled = settings->isPluginsEnabled(url().host());
05980   d->m_metaRefreshEnabled = settings->isAutoDelayedActionsEnabled ();
05981 
05982   delete d->m_settings;
05983   d->m_settings = new KHTMLSettings(*KHTMLGlobal::defaultHTMLSettings());
05984 
05985   QApplication::setOverrideCursor( Qt::WaitCursor );
05986   khtml::CSSStyleSelector::reparseConfiguration();
05987   if(d->m_doc) d->m_doc->updateStyleSelector();
05988   QApplication::restoreOverrideCursor();
05989 
05990   if (d->m_view) {
05991       KHTMLSettings::KSmoothScrollingMode ssm = d->m_settings->smoothScrolling();
05992       if (ssm == KHTMLSettings::KSmoothScrollingDisabled)
05993           d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled);
05994       else if (ssm == KHTMLSettings::KSmoothScrollingWhenEfficient)
05995           d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient);
05996       else
05997           d->m_view->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled);
05998   }
05999 
06000   if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled())
06001      runAdFilter();
06002 }
06003 
06004 QStringList KHTMLPart::frameNames() const
06005 {
06006   QStringList res;
06007 
06008   ConstFrameIt it = d->m_frames.constBegin();
06009   const ConstFrameIt end = d->m_frames.constEnd();
06010   for (; it != end; ++it )
06011     if (!(*it)->m_bPreloaded && (*it)->m_part)
06012       res += (*it)->m_name;
06013 
06014   return res;
06015 }
06016 
06017 QList<KParts::ReadOnlyPart*> KHTMLPart::frames() const
06018 {
06019   QList<KParts::ReadOnlyPart*> res;
06020 
06021   ConstFrameIt it = d->m_frames.constBegin();
06022   const ConstFrameIt end = d->m_frames.constEnd();
06023   for (; it != end; ++it )
06024     if (!(*it)->m_bPreloaded && (*it)->m_part) // ### TODO: make sure that we always create an empty
06025                                                // KHTMLPart for frames so this never happens.
06026       res.append( (*it)->m_part.data() );
06027 
06028   return res;
06029 }
06030 
06031 bool KHTMLPart::openUrlInFrame( const KUrl &url, const KParts::OpenUrlArguments& args, const KParts::BrowserArguments &browserArgs)
06032 {
06033   kDebug( 6031 ) << this << url;
06034   FrameIt it = d->m_frames.find( browserArgs.frameName );
06035 
06036   if ( it == d->m_frames.end() )
06037     return false;
06038 
06039   // Inform someone that we are about to show something else.
06040   if ( !browserArgs.lockHistory() )
06041       emit d->m_extension->openUrlNotify();
06042 
06043   requestObject( *it, url, args, browserArgs );
06044 
06045   return true;
06046 }
06047 
06048 void KHTMLPart::setDNDEnabled( bool b )
06049 {
06050   d->m_bDnd = b;
06051 }
06052 
06053 bool KHTMLPart::dndEnabled() const
06054 {
06055   return d->m_bDnd;
06056 }
06057 
06058 void KHTMLPart::customEvent( QEvent *event )
06059 {
06060   if ( khtml::MousePressEvent::test( event ) )
06061   {
06062     khtmlMousePressEvent( static_cast<khtml::MousePressEvent *>( event ) );
06063     return;
06064   }
06065 
06066   if ( khtml::MouseDoubleClickEvent::test( event ) )
06067   {
06068     khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent *>( event ) );
06069     return;
06070   }
06071 
06072   if ( khtml::MouseMoveEvent::test( event ) )
06073   {
06074     khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent *>( event ) );
06075     return;
06076   }
06077 
06078   if ( khtml::MouseReleaseEvent::test( event ) )
06079   {
06080     khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent *>( event ) );
06081     return;
06082   }
06083 
06084   if ( khtml::DrawContentsEvent::test( event ) )
06085   {
06086     khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent *>( event ) );
06087     return;
06088   }
06089 
06090   KParts::ReadOnlyPart::customEvent( event );
06091 }
06092 
06093 bool KHTMLPart::isPointInsideSelection(int x, int y)
06094 {
06095   // Treat a collapsed selection like no selection.
06096   if (d->editor_context.m_selection.state() == Selection::CARET)
06097     return false;
06098   if (!xmlDocImpl()->renderer())
06099     return false;
06100 
06101   khtml::RenderObject::NodeInfo nodeInfo(true, true);
06102   xmlDocImpl()->renderer()->layer()->nodeAtPoint(nodeInfo, x, y);
06103   NodeImpl *innerNode = nodeInfo.innerNode();
06104   if (!innerNode || !innerNode->renderer())
06105     return false;
06106 
06107   return innerNode->isPointInsideSelection(x, y, d->editor_context.m_selection);
06108 }
06109 
06115 static bool firstRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&startNode, long &startOffset)
06116 {
06117     for (khtml::RenderObject *n = renderNode; n; n = n->nextSibling()) {
06118         if (n->isText()) {
06119             khtml::RenderText* const textRenderer = static_cast<khtml::RenderText *>(n);
06120             for (khtml::InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
06121                 if (box->m_y == y && textRenderer->element()) {
06122                     startNode = textRenderer->element();
06123                     startOffset = box->m_start;
06124                     return true;
06125                 }
06126             }
06127         }
06128 
06129         if (firstRunAt(n->firstChild(), y, startNode, startOffset)) {
06130             return true;
06131         }
06132     }
06133 
06134     return false;
06135 }
06136 
06142 static bool lastRunAt(khtml::RenderObject *renderNode, int y, NodeImpl *&endNode, long &endOffset)
06143 {
06144     khtml::RenderObject *n = renderNode;
06145     if (!n) {
06146         return false;
06147     }
06148     khtml::RenderObject *next;
06149     while ((next = n->nextSibling())) {
06150         n = next;
06151     }
06152 
06153     while (1) {
06154         if (lastRunAt(n->firstChild(), y, endNode, endOffset)) {
06155             return true;
06156         }
06157 
06158         if (n->isText()) {
06159             khtml::RenderText* const textRenderer =  static_cast<khtml::RenderText *>(n);
06160             for (khtml::InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
06161                 if (box->m_y == y && textRenderer->element()) {
06162                     endNode = textRenderer->element();
06163                     endOffset = box->m_start + box->m_len;
06164                     return true;
06165                 }
06166             }
06167         }
06168 
06169         if (n == renderNode) {
06170             return false;
06171         }
06172 
06173         n = n->previousSibling();
06174     }
06175 }
06176 
06177 void KHTMLPart::handleMousePressEventDoubleClick(khtml::MouseDoubleClickEvent *event)
06178 {
06179     QMouseEvent *mouse = event->qmouseEvent();
06180     DOM::Node innerNode = event->innerNode();
06181 
06182     Selection selection;
06183 
06184     if (mouse->button() == Qt::LeftButton && !innerNode.isNull() && innerNode.handle()->renderer() &&
06185         innerNode.handle()->renderer()->shouldSelect()) {
06186         Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()).position());
06187         if (pos.node() && (pos.node()->nodeType() == Node::TEXT_NODE || pos.node()->nodeType() == Node::CDATA_SECTION_NODE)) {
06188             selection.moveTo(pos);
06189             selection.expandUsingGranularity(Selection::WORD);
06190         }
06191     }
06192 
06193     if (selection.state() != Selection::CARET) {
06194         d->editor_context.beginSelectingText(Selection::WORD);
06195     }
06196 
06197     setCaret(selection);
06198     startAutoScroll();
06199 }
06200 
06201 void KHTMLPart::handleMousePressEventTripleClick(khtml::MouseDoubleClickEvent *event)
06202 {
06203     QMouseEvent *mouse = event->qmouseEvent();
06204     DOM::Node innerNode = event->innerNode();
06205 
06206     Selection selection;
06207 
06208     if (mouse->button() == Qt::LeftButton && !innerNode.isNull() && innerNode.handle()->renderer() &&
06209         innerNode.handle()->renderer()->shouldSelect()) {
06210         Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()).position());
06211         if (pos.node() && (pos.node()->nodeType() == Node::TEXT_NODE || pos.node()->nodeType() == Node::CDATA_SECTION_NODE)) {
06212             selection.moveTo(pos);
06213             selection.expandUsingGranularity(Selection::LINE);
06214         }
06215     }
06216 
06217     if (selection.state() != Selection::CARET) {
06218         d->editor_context.beginSelectingText(Selection::LINE);
06219     }
06220 
06221     setCaret(selection);
06222     startAutoScroll();
06223 }
06224 
06225 void KHTMLPart::handleMousePressEventSingleClick(khtml::MousePressEvent *event)
06226 {
06227     QMouseEvent *mouse = event->qmouseEvent();
06228     DOM::Node innerNode = event->innerNode();
06229 
06230     if (mouse->button() == Qt::LeftButton) {
06231         Selection sel;
06232 
06233         if (!innerNode.isNull() && innerNode.handle()->renderer() &&
06234             innerNode.handle()->renderer()->shouldSelect()) {
06235             bool extendSelection = mouse->modifiers() & Qt::ShiftModifier;
06236 
06237             // Don't restart the selection when the mouse is pressed on an
06238             // existing selection so we can allow for text dragging.
06239             if (!extendSelection && isPointInsideSelection(event->x(), event->y())) {
06240                 return;
06241             }
06242             Position pos(innerNode.handle()->positionForCoordinates(event->x(), event->y()).position());
06243             if (pos.isEmpty())
06244                 pos = Position(innerNode.handle(), innerNode.handle()->caretMinOffset());
06245             kDebug(6050) << event->x() << event->y() << pos << endl;
06246 
06247             sel = caret();
06248             if (extendSelection && sel.notEmpty()) {
06249                 sel.clearModifyBias();
06250                 sel.setExtent(pos);
06251                 if (d->editor_context.m_selectionGranularity != Selection::CHARACTER) {
06252                     sel.expandUsingGranularity(d->editor_context.m_selectionGranularity);
06253                 }
06254                 d->editor_context.m_beganSelectingText = true;
06255             } else {
06256                 sel = pos;
06257                 d->editor_context.m_selectionGranularity = Selection::CHARACTER;
06258             }
06259         }
06260 
06261         setCaret(sel);
06262         startAutoScroll();
06263     }
06264 }
06265 
06266 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent *event )
06267 {
06268   DOM::DOMString url = event->url();
06269   QMouseEvent *_mouse = event->qmouseEvent();
06270   DOM::Node innerNode = event->innerNode();
06271   d->m_mousePressNode = innerNode;
06272 
06273   d->m_dragStartPos = QPoint(event->x(), event->y());
06274 
06275   if ( !event->url().isNull() ) {
06276     d->m_strSelectedURL = event->url().string();
06277     d->m_strSelectedURLTarget = event->target().string();
06278   }
06279   else {
06280     d->m_strSelectedURL.clear();
06281     d->m_strSelectedURLTarget.clear();
06282   }
06283 
06284   if ( _mouse->button() == Qt::LeftButton ||
06285        _mouse->button() == Qt::MidButton )
06286   {
06287     d->m_bMousePressed = true;
06288 
06289 #ifdef KHTML_NO_SELECTION
06290     d->m_dragLastPos = _mouse->globalPos();
06291 #else
06292     if ( _mouse->button() == Qt::LeftButton )
06293     {
06294       if ( (!d->m_strSelectedURL.isNull() && !isEditable())
06295                 || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) )
06296           return;
06297 
06298       d->editor_context.m_beganSelectingText = false;
06299 
06300       handleMousePressEventSingleClick(event);
06301     }
06302 #endif
06303   }
06304 
06305   if ( _mouse->button() == Qt::RightButton )
06306   {
06307     popupMenu( d->m_strSelectedURL );
06308     // might be deleted, don't touch "this"
06309   }
06310 }
06311 
06312 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent *event )
06313 {
06314   QMouseEvent *_mouse = event->qmouseEvent();
06315   if ( _mouse->button() == Qt::LeftButton )
06316   {
06317     d->m_bMousePressed = true;
06318     d->editor_context.m_beganSelectingText = false;
06319 
06320     if (event->clickCount() == 2) {
06321       handleMousePressEventDoubleClick(event);
06322       return;
06323     }
06324 
06325     if (event->clickCount() >= 3) {
06326       handleMousePressEventTripleClick(event);
06327       return;
06328     }
06329   }
06330 }
06331 
06332 #ifndef KHTML_NO_SELECTION
06333 bool KHTMLPart::isExtendingSelection() const
06334  {
06335   // This is it, the whole detection. khtmlMousePressEvent only sets this
06336   // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
06337   // it's sufficient to only rely on this flag to detect selection extension.
06338   return d->editor_context.m_beganSelectingText;
06339 }
06340 
06341 void KHTMLPart::extendSelectionTo(int x, int y, const DOM::Node &innerNode)
06342 {
06343     // handle making selection
06344     Position pos(innerNode.handle()->positionForCoordinates(x, y).position());
06345 
06346     // Don't modify the selection if we're not on a node.
06347     if (pos.isEmpty())
06348         return;
06349 
06350     // Restart the selection if this is the first mouse move. This work is usually
06351     // done in khtmlMousePressEvent, but not if the mouse press was on an existing selection.
06352     Selection sel = caret();
06353     sel.clearModifyBias();
06354     if (!d->editor_context.m_beganSelectingText) {
06355         // We are beginning a selection during press-drag, when the original click
06356         // wasn't appropriate for one. Make sure to set the granularity.
06357         d->editor_context.beginSelectingText(Selection::CHARACTER);
06358         sel.moveTo(pos);
06359     }
06360 
06361     sel.setExtent(pos);
06362     if (d->editor_context.m_selectionGranularity != Selection::CHARACTER) {
06363         sel.expandUsingGranularity(d->editor_context.m_selectionGranularity);
06364     }
06365     setCaret(sel);
06366 
06367 }
06368 #endif // KHTML_NO_SELECTION
06369 
06370 bool KHTMLPart::handleMouseMoveEventDrag(khtml::MouseMoveEvent *event)
06371 {
06372 #ifdef QT_NO_DRAGANDDROP
06373   return false;
06374 #else
06375   if (!dndEnabled())
06376     return false;
06377 
06378   DOM::Node innerNode = event->innerNode();
06379 
06380   if( (d->m_bMousePressed &&
06381        ( (!d->m_strSelectedURL.isEmpty() && !isEditable())
06382         || (!d->m_mousePressNode.isNull() && d->m_mousePressNode.elementId() == ID_IMG) ) )
06383         && ( d->m_dragStartPos - QPoint(event->x(), event->y()) ).manhattanLength() > KGlobalSettings::dndEventDelay() ) {
06384 
06385     DOM::DOMString url = event->url();
06386 
06387     QPixmap pix;
06388     HTMLImageElementImpl *img = 0L;
06389     KUrl u;
06390 
06391     // qDebug("****************** Event URL: %s", url.string().toLatin1().constData());
06392     // qDebug("****************** Event Target: %s", target.string().toLatin1().constData());
06393 
06394     // Normal image...
06395     if ( url.length() == 0 && innerNode.handle() && innerNode.handle()->id() == ID_IMG )
06396     {
06397       img = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06398       u = KUrl( completeURL( khtml::parseURL(img->getAttribute(ATTR_SRC)).string() ) );
06399       pix = KIconLoader::global()->loadIcon("image-x-generic", KIconLoader::Desktop);
06400     }
06401     else
06402     {
06403       // Text or image link...
06404       u = completeURL( d->m_strSelectedURL );
06405       pix = KIO::pixmapForUrl(u, 0, KIconLoader::Desktop, KIconLoader::SizeMedium);
06406     }
06407 
06408     u.setPass(QString());
06409 
06410     QDrag *drag = new QDrag( d->m_view->viewport() );
06411     QMap<QString, QString> metaDataMap;
06412     if ( !d->m_referrer.isEmpty() )
06413       metaDataMap.insert( "referrer", d->m_referrer );
06414     QMimeData* mimeData = new QMimeData();
06415     u.populateMimeData( mimeData, metaDataMap );
06416     drag->setMimeData( mimeData );
06417 
06418     if( img && img->complete() )
06419       drag->mimeData()->setImageData( img->currentImage() );
06420 
06421     if ( !pix.isNull() )
06422       drag->setPixmap( pix );
06423 
06424     stopAutoScroll();
06425     drag->start();
06426 
06427     // when we finish our drag, we need to undo our mouse press
06428     d->m_bMousePressed = false;
06429     d->m_strSelectedURL.clear();
06430     d->m_strSelectedURLTarget.clear();
06431     return true;
06432   }
06433   return false;
06434 #endif // QT_NO_DRAGANDDROP
06435 }
06436 
06437 bool KHTMLPart::handleMouseMoveEventOver(khtml::MouseMoveEvent *event)
06438 {
06439   // Mouse clicked -> do nothing
06440   if ( d->m_bMousePressed ) return false;
06441 
06442   DOM::DOMString url = event->url();
06443 
06444   // The mouse is over something
06445   if ( url.length() )
06446   {
06447     DOM::DOMString target = event->target();
06448     QMouseEvent *_mouse = event->qmouseEvent();
06449     DOM::Node innerNode = event->innerNode();
06450 
06451     bool shiftPressed = ( _mouse->modifiers() & Qt::ShiftModifier );
06452 
06453     // Image map
06454     if ( !innerNode.isNull() && innerNode.elementId() == ID_IMG )
06455     {
06456       HTMLImageElementImpl *i = static_cast<HTMLImageElementImpl *>(innerNode.handle());
06457       if ( i && i->isServerMap() )
06458       {
06459         khtml::RenderObject *r = i->renderer();
06460         if(r)
06461         {
06462           int absx, absy;
06463           r->absolutePosition(absx, absy);
06464           int x(event->x() - absx), y(event->y() - absy);
06465 
06466           d->m_overURL = url.string() + QString("?%1,%2").arg(x).arg(y);
06467           d->m_overURLTarget = target.string();
06468           overURL( d->m_overURL, target.string(), shiftPressed );
06469           return true;
06470         }
06471       }
06472     }
06473 
06474     // normal link
06475     if ( d->m_overURL.isEmpty() || d->m_overURL != url || d->m_overURLTarget != target )
06476     {
06477       d->m_overURL = url.string();
06478       d->m_overURLTarget = target.string();
06479       overURL( d->m_overURL, target.string(), shiftPressed );
06480     }
06481   }
06482   else  // Not over a link...
06483   {
06484     if( !d->m_overURL.isEmpty() ) // and we were over a link  -> reset to "default statusbar text"
06485     {
06486       // reset to "default statusbar text"
06487       resetHoverText();
06488     }
06489   }
06490   return true;
06491 }
06492 
06493 void KHTMLPart::handleMouseMoveEventSelection(khtml::MouseMoveEvent *event)
06494 {
06495     // Mouse not pressed. Do nothing.
06496     if (!d->m_bMousePressed)
06497         return;
06498 
06499 #ifdef KHTML_NO_SELECTION
06500     if (d->m_doc && d->m_view) {
06501         QPoint diff( mouse->globalPos() - d->m_dragLastPos );
06502 
06503         if (abs(diff.x()) > 64 || abs(diff.y()) > 64) {
06504             d->m_view->scrollBy(-diff.x(), -diff.y());
06505             d->m_dragLastPos = mouse->globalPos();
06506         }
06507     }
06508 #else
06509 
06510     QMouseEvent *mouse = event->qmouseEvent();
06511     DOM::Node innerNode = event->innerNode();
06512 
06513     if ( (mouse->buttons() & Qt::LeftButton) == 0 || !innerNode.handle() || !innerNode.handle()->renderer() ||
06514         !innerNode.handle()->renderer()->shouldSelect())
06515             return;
06516 
06517     // handle making selection
06518     extendSelectionTo(event->x(), event->y(), innerNode);
06519 #endif // KHTML_NO_SELECTION
06520 }
06521 
06522 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent *event )
06523 {
06524     if (handleMouseMoveEventDrag(event))
06525         return;
06526 
06527     if (handleMouseMoveEventOver(event))
06528         return;
06529 
06530     handleMouseMoveEventSelection(event);
06531 }
06532 
06533 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
06534 {
06535   DOM::Node innerNode = event->innerNode();
06536   d->m_mousePressNode = DOM::Node();
06537 
06538   if ( d->m_bMousePressed ) {
06539     setStatusBarText(QString(), BarHoverText);
06540     stopAutoScroll();
06541   }
06542 
06543   // Used to prevent mouseMoveEvent from initiating a drag before
06544   // the mouse is pressed again.
06545   d->m_bMousePressed = false;
06546 
06547   QMouseEvent *_mouse = event->qmouseEvent();
06548 #ifndef QT_NO_CLIPBOARD
06549   if ((d->m_guiProfile == BrowserViewGUI) && (_mouse->button() == Qt::MidButton) && (event->url().isNull())) {
06550     kDebug( 6050 ) << "MMB shouldOpen=" << d->m_bOpenMiddleClick;
06551 
06552     if (d->m_bOpenMiddleClick) {
06553       KHTMLPart *p = this;
06554       while (p->parentPart()) p = p->parentPart();
06555       p->d->m_extension->pasteRequest();
06556     }
06557   }
06558 #endif
06559 
06560 #ifndef KHTML_NO_SELECTION
06561   {
06562 
06563     // Clear the selection if the mouse didn't move after the last mouse press.
06564     // We do this so when clicking on the selection, the selection goes away.
06565     // However, if we are editing, place the caret.
06566     if (!d->editor_context.m_beganSelectingText
06567             && d->m_dragStartPos.x() == event->x()
06568             && d->m_dragStartPos.y() == event->y()
06569             && d->editor_context.m_selection.state() == Selection::RANGE) {
06570       Selection selection;
06571 #ifdef APPLE_CHANGES
06572       if (d->editor_context.m_selection.base().node()->isContentEditable())
06573 #endif
06574         selection.moveTo(d->editor_context.m_selection.base().node()->positionForCoordinates(event->x(), event->y()).position());
06575       setCaret(selection);
06576     }
06577     // get selected text and paste to the clipboard
06578 #ifndef QT_NO_CLIPBOARD
06579     QString text = selectedText();
06580     text.replace(QChar(0xa0), ' ');
06581     if (!text.isEmpty()) {
06582         disconnect( qApp->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
06583         qApp->clipboard()->setText(text,QClipboard::Selection);
06584         connect( qApp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
06585     }
06586 #endif
06587     //kDebug( 6000 ) << "selectedText = " << text;
06588     emitSelectionChanged();
06589 //kDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset();
06590   }
06591 #endif
06592 }
06593 
06594 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent * )
06595 {
06596 }
06597 
06598 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent *event )
06599 {
06600   if ( event->activated() )
06601   {
06602     emitSelectionChanged();
06603     emit d->m_extension->enableAction( "print", d->m_doc != 0 );
06604 
06605     if ( !d->m_settings->autoLoadImages() && d->m_paLoadImages )
06606     {
06607         QList<QAction*> lst;
06608         lst.append( d->m_paLoadImages );
06609         plugActionList( "loadImages", lst );
06610     }
06611   }
06612 }
06613 
06614 void KHTMLPart::slotPrintFrame()
06615 {
06616   if ( d->m_frames.count() == 0 )
06617     return;
06618 
06619   KParts::ReadOnlyPart *frame = currentFrame();
06620   if (!frame)
06621     return;
06622 
06623   KParts::BrowserExtension *ext = KParts::BrowserExtension::childObject( frame );
06624 
06625   if ( !ext )
06626     return;
06627 
06628 
06629   const QMetaObject *mo = ext->metaObject();
06630 
06631 
06632   if (mo->indexOfSlot( "print()") != -1)
06633     QMetaObject::invokeMethod(ext, "print()",  Qt::DirectConnection);
06634 }
06635 
06636 void KHTMLPart::slotSelectAll()
06637 {
06638   KParts::ReadOnlyPart *part = currentFrame();
06639   if (part && part->inherits("KHTMLPart"))
06640     static_cast<KHTMLPart *>(part)->selectAll();
06641 }
06642 
06643 void KHTMLPart::startAutoScroll()
06644 {
06645    connect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06646    d->m_scrollTimer.setSingleShot(false);
06647    d->m_scrollTimer.start(100);
06648 }
06649 
06650 void KHTMLPart::stopAutoScroll()
06651 {
06652    disconnect(&d->m_scrollTimer, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
06653    if (d->m_scrollTimer.isActive())
06654        d->m_scrollTimer.stop();
06655 }
06656 
06657 
06658 void KHTMLPart::slotAutoScroll()
06659 {
06660     if (d->m_view)
06661       d->m_view->doAutoScroll();
06662     else
06663       stopAutoScroll(); // Safety
06664 }
06665 
06666 void KHTMLPart::runAdFilter()
06667 {
06668     if ( parentPart() )
06669         parentPart()->runAdFilter();
06670 
06671     if ( !d->m_doc )
06672         return;
06673 
06674     QSetIterator<khtml::CachedObject*> it( d->m_doc->docLoader()->m_docObjects );
06675     while (it.hasNext())
06676     {
06677         khtml::CachedObject* obj = it.next();
06678         if ( obj->type() == khtml::CachedObject::Image ) {
06679             khtml::CachedImage *image = static_cast<khtml::CachedImage *>(obj);
06680             bool wasBlocked = image->m_wasBlocked;
06681             image->m_wasBlocked = KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( image->url().string() ) );
06682             if ( image->m_wasBlocked != wasBlocked )
06683                 image->do_notify(QRect(QPoint(0,0), image->pixmap_size()));
06684         }
06685     }
06686 
06687     if ( KHTMLGlobal::defaultHTMLSettings()->isHideAdsEnabled() ) {
06688         for ( NodeImpl *nextNode, *node = d->m_doc; node; node = nextNode ) {
06689 
06690             // We might be deleting 'node' shortly.
06691             nextNode = node->traverseNextNode();
06692 
06693             if ( node->id() == ID_IMG ||
06694                  node->id() == ID_IFRAME ||
06695                  (node->id() == ID_INPUT && static_cast<HTMLInputElementImpl *>(node)->inputType() == HTMLInputElementImpl::IMAGE ))
06696             {
06697                 if ( KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d->m_doc->completeURL( static_cast<ElementImpl *>(node)->getAttribute(ATTR_SRC).string() ) ) )
06698                 {
06699                     // Since any kids of node will be deleted, too, fastforward nextNode
06700                     // until we get outside of node.
06701                     while (nextNode && nextNode->isAncestor(node))
06702                         nextNode = nextNode->traverseNextNode();
06703 
06704                     node->ref();
06705                     NodeImpl *parent = node->parent();
06706                     if( parent )
06707                     {
06708                         int exception = 0;
06709                         parent->removeChild(node, exception);
06710                     }
06711                     node->deref();
06712                 }
06713             }
06714         }
06715     }
06716 }
06717 
06718 void KHTMLPart::selectAll()
06719 {
06720   if (!d->m_doc) return;
06721 
06722   NodeImpl *first;
06723   if (d->m_doc->isHTMLDocument())
06724     first = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06725   else
06726     first = d->m_doc;
06727   NodeImpl *next;
06728 
06729   // Look for first text/cdata node that has a renderer,
06730   // or first childless replaced element
06731   while ( first && !(first->renderer()
06732           && ((first->nodeType() == Node::TEXT_NODE || first->nodeType() == Node::CDATA_SECTION_NODE)
06733                 || (first->renderer()->isReplaced() && !first->renderer()->firstChild()))))
06734   {
06735     next = first->firstChild();
06736     if ( !next ) next = first->nextSibling();
06737     while( first && !next )
06738     {
06739       first = first->parentNode();
06740       if ( first )
06741         next = first->nextSibling();
06742     }
06743     first = next;
06744   }
06745 
06746   NodeImpl *last;
06747   if (d->m_doc->isHTMLDocument())
06748     last = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
06749   else
06750     last = d->m_doc;
06751   // Look for last text/cdata node that has a renderer,
06752   // or last childless replaced element
06753   // ### Instead of changing this loop, use findLastSelectableNode
06754   // in render_table.cpp (LS)
06755   while ( last && !(last->renderer()
06756           && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
06757                 || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
06758   {
06759     next = last->lastChild();
06760     if ( !next ) next = last->previousSibling();
06761     while ( last && !next )
06762     {
06763       last = last->parentNode();
06764       if ( last )
06765         next = last->previousSibling();
06766     }
06767     last = next;
06768   }
06769 
06770   if ( !first || !last )
06771     return;
06772   Q_ASSERT(first->renderer());
06773   Q_ASSERT(last->renderer());
06774   d->editor_context.m_selection.moveTo(Position(first, 0), Position(last, last->nodeValue().length()));
06775   d->m_doc->updateSelection();
06776 
06777   emitSelectionChanged();
06778 }
06779 
06780 bool KHTMLPart::checkLinkSecurity(const KUrl &linkURL,const KLocalizedString &message, const QString &button)
06781 {
06782   bool linkAllowed = true;
06783 
06784   if ( d->m_doc )
06785     linkAllowed = KAuthorized::authorizeUrlAction("redirect", url(), linkURL);
06786 
06787   if ( !linkAllowed ) {
06788     khtml::Tokenizer *tokenizer = d->m_doc->tokenizer();
06789     if (tokenizer)
06790       tokenizer->setOnHold(true);
06791 
06792     int response = KMessageBox::Cancel;
06793     if (!message.isEmpty())
06794     {
06795             // Dangerous flag makes the Cancel button the default
06796             response = KMessageBox::warningContinueCancel( 0,
06797                                                            message.subs(Qt::escape(linkURL.prettyUrl())).toString(),
06798                                                            i18n( "Security Warning" ),
06799                                                            KGuiItem(button),
06800                                                            KStandardGuiItem::cancel(),
06801                                                            QString(), // no don't ask again info
06802                                                            KMessageBox::Notify | KMessageBox::Dangerous );
06803     }
06804     else
06805     {
06806             KMessageBox::error( 0,
06807                                 i18n( "<qt>Access by untrusted page to<br /><b>%1</b><br /> denied.</qt>", Qt::escape(linkURL.prettyUrl())),
06808                                 i18n( "Security Alert" ));
06809     }
06810 
06811     if (tokenizer)
06812        tokenizer->setOnHold(false);
06813     return (response==KMessageBox::Continue);
06814   }
06815   return true;
06816 }
06817 
06818 void KHTMLPart::slotPartRemoved( KParts::Part *part )
06819 {
06820 //    kDebug(6050) << part;
06821     if ( part == d->m_activeFrame )
06822     {
06823         d->m_activeFrame = 0L;
06824         if ( !part->inherits( "KHTMLPart" ) )
06825         {
06826             if (factory()) {
06827                 factory()->removeClient( part );
06828             }
06829             if (childClients().contains(part)) {
06830                 removeChildClient( part );
06831             }
06832         }
06833     }
06834 }
06835 
06836 void KHTMLPart::slotActiveFrameChanged( KParts::Part *part )
06837 {
06838 //    kDebug(6050) << this << "part=" << part;
06839     if ( part == this )
06840     {
06841         kError(6050) << "strange error! we activated ourselves";
06842         assert( false );
06843         return;
06844     }
06845 //    kDebug(6050) << "d->m_activeFrame=" << d->m_activeFrame;
06846     if ( d->m_activeFrame && d->m_activeFrame->widget() && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06847     {
06848         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06849         if (frame->frameStyle() != QFrame::NoFrame)
06850         {
06851            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken);
06852            frame->repaint();
06853         }
06854     }
06855 
06856     if( d->m_activeFrame && !d->m_activeFrame->inherits( "KHTMLPart" ) )
06857     {
06858         if (factory()) {
06859             factory()->removeClient( d->m_activeFrame );
06860         }
06861         removeChildClient( d->m_activeFrame );
06862     }
06863     if( part && !part->inherits( "KHTMLPart" ) )
06864     {
06865         if (factory()) {
06866             factory()->addClient( part );
06867         }
06868         insertChildClient( part );
06869     }
06870 
06871 
06872     d->m_activeFrame = part;
06873 
06874     if ( d->m_activeFrame && d->m_activeFrame->widget()->inherits( "QFrame" ) )
06875     {
06876         QFrame *frame = static_cast<QFrame *>( d->m_activeFrame->widget() );
06877         if (frame->frameStyle() != QFrame::NoFrame)
06878         {
06879            frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain);
06880            frame->repaint();
06881         }
06882         kDebug(6050) << "new active frame " << d->m_activeFrame;
06883     }
06884 
06885     updateActions();
06886 
06887     // (note: childObject returns 0 if the argument is 0)
06888     d->m_extension->setExtensionProxy( KParts::BrowserExtension::childObject( d->m_activeFrame ) );
06889 }
06890 
06891 void KHTMLPart::setActiveNode(const DOM::Node &node)
06892 {
06893     if (!d->m_doc || !d->m_view)
06894         return;
06895 
06896     // Set the document's active node
06897     d->m_doc->setFocusNode(node.handle());
06898 
06899     // Scroll the view if necessary to ensure that the new focus node is visible
06900     QRect rect  = node.handle()->getRect();
06901     d->m_view->ensureVisible(rect.right(), rect.bottom());
06902     d->m_view->ensureVisible(rect.left(), rect.top());
06903 }
06904 
06905 DOM::Node KHTMLPart::activeNode() const
06906 {
06907     return DOM::Node(d->m_doc?d->m_doc->focusNode():0);
06908 }
06909 
06910 DOM::EventListener *KHTMLPart::createHTMLEventListener( QString code, QString name, NodeImpl* node, bool svg )
06911 {
06912   KJSProxy *proxy = jScript();
06913 
06914   if (!proxy)
06915     return 0;
06916 
06917   return proxy->createHTMLEventHandler( url().url(), name, code, node, svg );
06918 }
06919 
06920 KHTMLPart *KHTMLPart::opener()
06921 {
06922     return d->m_opener;
06923 }
06924 
06925 void KHTMLPart::setOpener(KHTMLPart *_opener)
06926 {
06927     d->m_opener = _opener;
06928 }
06929 
06930 bool KHTMLPart::openedByJS()
06931 {
06932     return d->m_openedByJS;
06933 }
06934 
06935 void KHTMLPart::setOpenedByJS(bool _openedByJS)
06936 {
06937     d->m_openedByJS = _openedByJS;
06938 }
06939 
06940 void KHTMLPart::preloadStyleSheet(const QString &url, const QString &stylesheet)
06941 {
06942     khtml::Cache::preloadStyleSheet(url, stylesheet);
06943 }
06944 
06945 void KHTMLPart::preloadScript(const QString &url, const QString &script)
06946 {
06947     khtml::Cache::preloadScript(url, script);
06948 }
06949 
06950 long KHTMLPart::cacheId() const
06951 {
06952   return d->m_cacheId;
06953 }
06954 
06955 bool KHTMLPart::restored() const
06956 {
06957   return d->m_restored;
06958 }
06959 
06960 bool KHTMLPart::pluginPageQuestionAsked(const QString& mimetype) const
06961 {
06962   // parentPart() should be const!
06963   KHTMLPart* parent = const_cast<KHTMLPart *>(this)->parentPart();
06964   if ( parent )
06965     return parent->pluginPageQuestionAsked(mimetype);
06966 
06967   return d->m_pluginPageQuestionAsked.contains(mimetype);
06968 }
06969 
06970 void KHTMLPart::setPluginPageQuestionAsked(const QString& mimetype)
06971 {
06972   if ( parentPart() )
06973     parentPart()->setPluginPageQuestionAsked(mimetype);
06974 
06975   d->m_pluginPageQuestionAsked.append(mimetype);
06976 }
06977 
06978 KEncodingDetector *KHTMLPart::createDecoder()
06979 {
06980     KEncodingDetector *dec = new KEncodingDetector();
06981     if( !d->m_encoding.isNull() )
06982         dec->setEncoding( d->m_encoding.toLatin1().constData(),
06983             d->m_haveEncoding ? KEncodingDetector::UserChosenEncoding : KEncodingDetector::EncodingFromHTTPHeader);
06984     else {
06985         // Inherit the default encoding from the parent frame if there is one.
06986         QByteArray defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
06987             ? QByteArray( parentPart()->d->m_decoder->encoding() ) : settings()->encoding().toLatin1();
06988         dec->setEncoding(defaultEncoding.constData(), KEncodingDetector::DefaultEncoding);
06989     }
06990 
06991     if (d->m_doc)
06992         d->m_doc->setDecoder(dec);
06993     dec->setAutoDetectLanguage( d->m_autoDetectLanguage );
06994     return dec;
06995 }
06996 
06997 void KHTMLPart::emitCaretPositionChanged(const DOM::Position &pos) {
06998   // pos must not be already converted to range-compliant coordinates
06999   Position rng_pos = pos.equivalentRangeCompliantPosition();
07000   Node node = rng_pos.node();
07001   emit caretPositionChanged(node, rng_pos.offset());
07002 }
07003 
07004 void KHTMLPart::restoreScrollPosition()
07005 {
07006   const KParts::OpenUrlArguments args( arguments() );
07007 
07008   if ( url().hasRef() && !d->m_restoreScrollPosition && !args.reload()) {
07009     if ( !d->m_doc || !d->m_doc->parsing() )
07010       disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07011     if ( !gotoAnchor(url().encodedHtmlRef()) )
07012       gotoAnchor(url().htmlRef());
07013     return;
07014   }
07015 
07016   // Check whether the viewport has become large enough to encompass the stored
07017   // offsets. If the document has been fully loaded, force the new coordinates,
07018   // even if the canvas is too short (can happen when user resizes the window
07019   // during loading).
07020   if (d->m_view->contentsHeight() - d->m_view->visibleHeight() >= args.yOffset()
07021       || d->m_bComplete) {
07022     d->m_view->setContentsPos(args.xOffset(), args.yOffset());
07023     disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
07024   }
07025 }
07026 
07027 
07028 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl *form)
07029 {
07030 #ifndef KHTML_NO_WALLET
07031   KHTMLPart *p;
07032 
07033   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07034   }
07035 
07036   if (p) {
07037     p->openWallet(form);
07038     return;
07039   }
07040 
07041   if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
07042     return;
07043   }
07044 
07045   if (d->m_wallet) {
07046     if (d->m_bWalletOpened) {
07047       if (d->m_wallet->isOpen()) {
07048         form->walletOpened(d->m_wallet);
07049         return;
07050       }
07051       d->m_wallet->deleteLater();
07052       d->m_wallet = 0L;
07053       d->m_bWalletOpened = false;
07054     }
07055   }
07056 
07057   if (!d->m_wq) {
07058     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07059     d->m_wq = new KHTMLWalletQueue(this);
07060     d->m_wq->wallet = wallet;
07061     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07062     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07063   }
07064   assert(form);
07065   d->m_wq->callers.append(KHTMLWalletQueue::Caller(form, form->document()));
07066 #endif // KHTML_NO_WALLET
07067 }
07068 
07069 
07070 void KHTMLPart::saveToWallet(const QString& key, const QMap<QString,QString>& data)
07071 {
07072 #ifndef KHTML_NO_WALLET
07073   KHTMLPart *p;
07074 
07075   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07076   }
07077 
07078   if (p) {
07079     p->saveToWallet(key, data);
07080     return;
07081   }
07082 
07083   if (d->m_wallet) {
07084     if (d->m_bWalletOpened) {
07085       if (d->m_wallet->isOpen()) {
07086         if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder())) {
07087           d->m_wallet->createFolder(KWallet::Wallet::FormDataFolder());
07088         }
07089         d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
07090         d->m_wallet->writeMap(key, data);
07091         return;
07092       }
07093       d->m_wallet->deleteLater();
07094       d->m_wallet = 0L;
07095       d->m_bWalletOpened = false;
07096     }
07097   }
07098 
07099   if (!d->m_wq) {
07100     KWallet::Wallet *wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous);
07101     d->m_wq = new KHTMLWalletQueue(this);
07102     d->m_wq->wallet = wallet;
07103     connect(wallet, SIGNAL(walletOpened(bool)), d->m_wq, SLOT(walletOpened(bool)));
07104     connect(d->m_wq, SIGNAL(walletOpened(KWallet::Wallet*)), this, SLOT(walletOpened(KWallet::Wallet*)));
07105   }
07106   d->m_wq->savers.append(qMakePair(key, data));
07107 #endif // KHTML_NO_WALLET
07108 }
07109 
07110 
07111 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl *form) {
07112 #ifndef KHTML_NO_WALLET
07113   KHTMLPart *p;
07114 
07115   for (p = parentPart(); p && p->parentPart(); p = p->parentPart()) {
07116   }
07117 
07118   if (p) {
07119     p->dequeueWallet(form);
07120     return;
07121   }
07122 
07123   if (d->m_wq) {
07124     d->m_wq->callers.removeAll(KHTMLWalletQueue::Caller(form, form->document()));
07125   }
07126 #endif // KHTML_NO_WALLET
07127 }
07128 
07129 
07130 void KHTMLPart::walletOpened(KWallet::Wallet *wallet) {
07131 #ifndef KHTML_NO_WALLET
07132   assert(!d->m_wallet);
07133   assert(d->m_wq);
07134 
07135   d->m_wq->deleteLater(); // safe?
07136   d->m_wq = 0L;
07137 
07138   if (!wallet) {
07139     d->m_bWalletOpened = false;
07140     return;
07141   }
07142 
07143   d->m_wallet = wallet;
07144   d->m_bWalletOpened = true;
07145   connect(d->m_wallet, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
07146   d->m_walletForms.clear();
07147   if (!d->m_statusBarWalletLabel) {
07148     d->m_statusBarWalletLabel = new KUrlLabel(d->m_statusBarExtension->statusBar());
07149     d->m_statusBarWalletLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
07150     d->m_statusBarWalletLabel->setUseCursor(false);
07151     d->m_statusBarExtension->addStatusBarItem(d->m_statusBarWalletLabel, 0, false);
07152     d->m_statusBarWalletLabel->setPixmap(SmallIcon("wallet-open"));
07153     connect(d->m_statusBarWalletLabel, SIGNAL(leftClickedUrl()), SLOT(launchWalletManager()));
07154     connect(d->m_statusBarWalletLabel, SIGNAL(rightClickedUrl()), SLOT(walletMenu()));
07155   }
07156   d->m_statusBarWalletLabel->setToolTip(i18n("The wallet '%1' is open and being used for form data and passwords.", KWallet::Wallet::NetworkWallet()));
07157 #endif // KHTML_NO_WALLET
07158 }
07159 
07160 
07161 KWallet::Wallet *KHTMLPart::wallet()
07162 {
07163 #ifndef KHTML_NO_WALLET
07164   KHTMLPart *p;
07165 
07166   for (p = parentPart(); p && p->parentPart(); p = p->parentPart())
07167     ;
07168 
07169   if (p)
07170     return p->wallet();
07171 
07172   return d->m_wallet;
07173 #else
07174   return 0;
07175 #endif // !KHTML_NO_WALLET
07176 }
07177 
07178 
07179 void KHTMLPart::slotWalletClosed()
07180 {
07181 #ifndef KHTML_NO_WALLET
07182   if (d->m_wallet) {
07183     d->m_wallet->deleteLater();
07184     d->m_wallet = 0L;
07185   }
07186   d->m_bWalletOpened = false;
07187   if (d->m_statusBarWalletLabel) {
07188     d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarWalletLabel);
07189     delete d->m_statusBarWalletLabel;
07190     d->m_statusBarWalletLabel = 0L;
07191   }
07192 #endif // KHTML_NO_WALLET
07193 }
07194 
07195 void KHTMLPart::launchWalletManager()
07196 {
07197 #ifndef KHTML_NO_WALLET
07198   QDBusInterface r("org.kde.kwalletmanager", "/kwalletmanager/MainWindow_1",
07199                       "org.kde.KMainWindow");
07200   if (!r.isValid()) {
07201     KToolInvocation::startServiceByDesktopName("kwalletmanager_show");
07202   } else {
07203     r.call(QDBus::NoBlock, "show");
07204     r.call(QDBus::NoBlock, "raise");
07205   }
07206 #endif // KHTML_NO_WALLET
07207 }
07208 
07209 void KHTMLPart::walletMenu()
07210 {
07211 #ifndef KHTML_NO_WALLET
07212   KMenu *menu = new KMenu(0L);
07213   QActionGroup *menuActionGroup = new QActionGroup(menu);
07214   connect( menuActionGroup, SIGNAL(triggered(QAction*)), this, SLOT(removeStoredPasswordForm(QAction*)) );
07215 
07216   menu->addAction(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
07217 
07218   if (d->m_view && d->m_view->nonPasswordStorableSite(toplevelURL().host())) {
07219     menu->addAction(i18n("&Allow storing passwords for this site"), this, SLOT(delNonPasswordStorableSite()));
07220   }
07221 
07222   // List currently removable form passwords
07223   for ( QStringList::ConstIterator it = d->m_walletForms.constBegin(); it != d->m_walletForms.constEnd(); ++it ) {
07224       QAction* action = menu->addAction( i18n("Remove password for form %1", *it) );
07225       action->setActionGroup(menuActionGroup);
07226       QVariant var(*it);
07227       action->setData(var);
07228   }
07229 
07230   KAcceleratorManager::manage(menu);
07231   menu->popup(QCursor::pos());
07232 #endif // KHTML_NO_WALLET
07233 }
07234 
07235 void KHTMLPart::removeStoredPasswordForm(QAction* action)
07236 {
07237 #ifndef KHTML_NO_WALLET
07238   assert(action);
07239   assert(d->m_wallet);
07240   QVariant var(action->data());
07241 
07242   if(var.isNull() || !var.isValid() || var.type() != QVariant::String)
07243     return;
07244 
07245   QString key = var.toString();
07246   if (KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(),
07247                                       KWallet::Wallet::FormDataFolder(),
07248                                       key))
07249     return; // failed
07250 
07251 
07252   if (!d->m_wallet->hasFolder(KWallet::Wallet::FormDataFolder()))
07253     return; // failed
07254 
07255   d->m_wallet->setFolder(KWallet::Wallet::FormDataFolder());
07256   if (d->m_wallet->removeEntry(key))
07257     return; // failed
07258 
07259   d->m_walletForms.removeAll(key);
07260 #endif // KHTML_NO_WALLET
07261 }
07262 
07263 void KHTMLPart::addWalletFormKey(const QString& walletFormKey)
07264 {
07265 #ifndef KHTML_NO_WALLET
07266 
07267   if (parentPart()) {
07268     parentPart()->addWalletFormKey(walletFormKey);
07269     return;
07270   }
07271 
07272   if(!d->m_walletForms.contains(walletFormKey))
07273     d->m_walletForms.append(walletFormKey);
07274 #endif // KHTML_NO_WALLET
07275 }
07276 
07277 void KHTMLPart::delNonPasswordStorableSite()
07278 {
07279 #ifndef KHTML_NO_WALLET
07280   if (d->m_view)
07281     d->m_view->delNonPasswordStorableSite(toplevelURL().host());
07282 #endif // KHTML_NO_WALLET
07283 }
07284 void KHTMLPart::saveLoginInformation(const QString& host, const QString& key, const QMap<QString, QString>& walletMap)
07285 {
07286 #ifndef KHTML_NO_WALLET
07287   d->m_storePass.saveLoginInformation(host, key, walletMap);
07288 #endif // KHTML_NO_WALLET
07289 }
07290 
07291 void KHTMLPart::slotToggleCaretMode()
07292 {
07293   setCaretMode(d->m_paToggleCaretMode->isChecked());
07294 }
07295 
07296 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn) {
07297   d->m_formNotification = fn;
07298 }
07299 
07300 KHTMLPart::FormNotification KHTMLPart::formNotification() const {
07301   return d->m_formNotification;
07302 }
07303 
07304 KUrl KHTMLPart::toplevelURL()
07305 {
07306   KHTMLPart* part = this;
07307   while (part->parentPart())
07308     part = part->parentPart();
07309 
07310   if (!part)
07311     return KUrl();
07312 
07313   return part->url();
07314 }
07315 
07316 bool KHTMLPart::isModified() const
07317 {
07318   if ( !d->m_doc )
07319     return false;
07320 
07321   return d->m_doc->unsubmittedFormChanges();
07322 }
07323 
07324 void KHTMLPart::setDebugScript( bool enable )
07325 {
07326   unplugActionList( "debugScriptList" );
07327   if ( enable ) {
07328     if (!d->m_paDebugScript) {
07329       d->m_paDebugScript = new KAction( i18n( "JavaScript &Debugger" ), this );
07330       actionCollection()->addAction( "debugScript", d->m_paDebugScript );
07331       connect( d->m_paDebugScript, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugScript() ) );
07332     }
07333     d->m_paDebugScript->setEnabled( d->m_frame ? d->m_frame->m_jscript : 0L );
07334     QList<QAction*> lst;
07335     lst.append( d->m_paDebugScript );
07336     plugActionList( "debugScriptList", lst );
07337   }
07338   d->m_bJScriptDebugEnabled = enable;
07339 }
07340 
07341 void KHTMLPart::setSuppressedPopupIndicator( bool enable, KHTMLPart *originPart )
07342 {
07343     if ( parentPart() ) {
07344         parentPart()->setSuppressedPopupIndicator( enable, originPart );
07345         return;
07346     }
07347 
07348     if ( enable && originPart ) {
07349         d->m_openableSuppressedPopups++;
07350         if ( d->m_suppressedPopupOriginParts.indexOf( originPart ) == -1 )
07351             d->m_suppressedPopupOriginParts.append( originPart );
07352     }
07353 
07354     if ( enable && !d->m_statusBarPopupLabel ) {
07355         d->m_statusBarPopupLabel = new KUrlLabel( d->m_statusBarExtension->statusBar() );
07356         d->m_statusBarPopupLabel->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Minimum ));
07357         d->m_statusBarPopupLabel->setUseCursor( false );
07358         d->m_statusBarExtension->addStatusBarItem( d->m_statusBarPopupLabel, 0, false );
07359         d->m_statusBarPopupLabel->setPixmap( SmallIcon( "window-suppressed") );
07360 
07361                 d->m_statusBarPopupLabel->setToolTip(i18n("This page was prevented from opening a new window via JavaScript." ) );
07362 
07363         connect(d->m_statusBarPopupLabel, SIGNAL(leftClickedUrl()), SLOT(suppressedPopupMenu()));
07364         if (d->m_settings->jsPopupBlockerPassivePopup()) {
07365             QPixmap px;
07366             px = MainBarIcon( "window-suppressed" );
07367             KPassivePopup::message(i18n("Popup Window Blocked"),i18n("This page has attempted to open a popup window but was blocked.\nYou can click on this icon in the status bar to control this behavior\nor to open the popup."),px,d->m_statusBarPopupLabel);
07368         }
07369     } else if ( !enable && d->m_statusBarPopupLabel ) {
07370         d->m_statusBarPopupLabel->setToolTip("" );
07371         d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarPopupLabel );
07372         delete d->m_statusBarPopupLabel;
07373         d->m_statusBarPopupLabel = 0L;
07374     }
07375 }
07376 
07377 void KHTMLPart::suppressedPopupMenu() {
07378   KMenu *m = new KMenu(0L);
07379   if ( d->m_openableSuppressedPopups )
07380       m->addAction(i18np("&Show Blocked Popup Window","&Show %1 Blocked Popup Windows", d->m_openableSuppressedPopups), this, SLOT(showSuppressedPopups()));
07381   QAction *a = m->addAction(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()));
07382   a->setChecked(d->m_settings->jsPopupBlockerPassivePopup());
07383   m->addAction(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
07384   m->popup(QCursor::pos());
07385 }
07386 
07387 void KHTMLPart::togglePopupPassivePopup() {
07388   // Same hack as in disableJSErrorExtension()
07389   d->m_settings->setJSPopupBlockerPassivePopup( !d->m_settings->jsPopupBlockerPassivePopup() );
07390   emit configurationChanged();
07391 }
07392 
07393 void KHTMLPart::showSuppressedPopups() {
07394     foreach ( KHTMLPart* part, d->m_suppressedPopupOriginParts ) {
07395       if (part) {
07396         KJS::Window *w = KJS::Window::retrieveWindow( part );
07397         if (w) {
07398           w->showSuppressedWindows();
07399           w->forgetSuppressedWindows();
07400         }
07401       }
07402     }
07403     setSuppressedPopupIndicator( false );
07404     d->m_openableSuppressedPopups = 0;
07405     d->m_suppressedPopupOriginParts.clear();
07406 }
07407 
07408 // Extension to use for "view document source", "save as" etc.
07409 // Using the right extension can help the viewer get into the right mode (#40496)
07410 QString KHTMLPart::defaultExtension() const
07411 {
07412     if ( !d->m_doc )
07413         return ".html";
07414     if ( !d->m_doc->isHTMLDocument() )
07415         return ".xml";
07416     return d->m_doc->htmlMode() == DOM::DocumentImpl::XHtml ? ".xhtml" : ".html";
07417 }
07418 
07419 bool KHTMLPart::inProgress() const
07420 {
07421     if (!d->m_bComplete || d->m_runningScripts || (d->m_doc && d->m_doc->parsing()))
07422         return true;
07423 
07424     // Any frame that hasn't completed yet ?
07425     ConstFrameIt it = d->m_frames.constBegin();
07426     const ConstFrameIt end = d->m_frames.constEnd();
07427     for (; it != end; ++it ) {
07428         if ((*it)->m_run || !(*it)->m_bCompleted)
07429             return true;
07430     }
07431 
07432     return d->m_submitForm || !d->m_redirectURL.isEmpty() || d->m_redirectionTimer.isActive() || d->m_job;
07433 }
07434 
07435 using namespace KParts;
07436 #include "khtml_part.moc"
07437 #include "khtmlpart_p.moc"
07438 #ifndef KHTML_NO_WALLET
07439 #include "khtml_wallet_p.moc"
07440 #endif
07441 
07442 // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal