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

KDE's Doxygen guidelines are available online.

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-4.9.5 API Reference

Skip menu "kdelibs-4.9.5 API Reference"
  • 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
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal