diff --git a/khtml/khtml_part.cpp b/khtml/khtml_part.cpp
index ede7aab574..d3ab80e96a 100644
--- a/khtml/khtml_part.cpp
+++ b/khtml/khtml_part.cpp
@@ -1,6893 +1,6896 @@
// -*- c-basic-offset: 2 -*-
/* This file is part of the KDE project
*
* Copyright (C) 1998, 1999 Torben Weis
* 1999 Lars Knoll
* 1999 Antti Koivisto
* 2000 Simon Hausmann
* 2000 Stefan Schimanski <1Stein@gmx.de>
* 2001-2003 George Staikos
* 2001-2003 Dirk Mueller
* 2002 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
//#define SPEED_DEBUG
#include "khtml_part.h"
#include "khtml_pagecache.h"
#include "dom/dom_string.h"
#include "dom/dom_element.h"
#include "html/html_documentimpl.h"
#include "html/html_baseimpl.h"
#include "html/html_objectimpl.h"
#include "html/html_miscimpl.h"
#include "html/html_imageimpl.h"
#include "html/html_objectimpl.h"
#include "rendering/render_text.h"
#include "rendering/render_frames.h"
#include "rendering/render_layer.h"
#include "misc/htmlhashes.h"
#include "misc/loader.h"
#include "xml/dom2_eventsimpl.h"
#include "xml/dom2_rangeimpl.h"
#include "xml/xml_tokenizer.h"
#include "css/cssstyleselector.h"
#include "css/csshelper.h"
using namespace DOM;
#include "khtmlview.h"
#include
#include "ecma/kjs_proxy.h"
#include "khtml_settings.h"
#include "kjserrordlg.h"
#include
#include
#include "htmlpageinfo.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#if !defined(QT_NO_DRAGANDDROP)
#include
#endif
#include "../kutils/kfinddialog.h"
#include "../kutils/kfind.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "khtmlpart_p.h"
#include "kpopupmenu.h"
#include "rendering/render_form.h"
#include
#define HINT_UTF8 106
namespace khtml {
class PartStyleSheetLoader : public CachedObjectClient
{
public:
PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
{
m_part = part;
m_cachedSheet = dl->requestStyleSheet(url, QString::null, "text/css",
true /* "user sheet" */);
if (m_cachedSheet)
m_cachedSheet->ref( this );
}
virtual ~PartStyleSheetLoader()
{
if ( m_cachedSheet ) m_cachedSheet->deref(this);
}
virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet)
{
if ( m_part )
m_part->setUserStyleSheet( sheet.string() );
delete this;
}
virtual void error( int, const QString& ) {
delete this;
}
QGuardedPtr m_part;
khtml::CachedCSSStyleSheet *m_cachedSheet;
};
}
void khtml::ChildFrame::liveConnectEvent(const unsigned long, const QString & event, const KParts::LiveConnectExtension::ArgList & args)
{
if (!m_part || !m_frame || !m_liveconnect)
// hmmm
return;
QString script;
script.sprintf("%s(", event.latin1());
KParts::LiveConnectExtension::ArgList::const_iterator i = args.begin();
const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin = i;
const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd = args.end();
for ( ; i != argsEnd; ++i) {
if (i != argsBegin)
script += ",";
if ((*i).first == KParts::LiveConnectExtension::TypeString) {
script += "\"";
script += QString((*i).second).replace('\\', "\\\\").replace('"', "\\\"");
script += "\"";
} else
script += (*i).second;
}
script += ")";
kdDebug(6050) << "khtml::ChildFrame::liveConnectEvent " << script << endl;
KHTMLPart * part = ::qt_cast(m_part->parent());
if (!part)
return;
if (!m_jscript)
part->framejScript(m_part);
if (m_jscript) {
// we have a jscript => a part in an iframe
KJS::Completion cmp;
m_jscript->evaluate(QString::null, 1, script, 0L, &cmp);
} else
part->executeScript(m_frame->element(), script);
}
KHTMLFrameList::Iterator KHTMLFrameList::find( const QString &name )
{
Iterator it = begin();
const Iterator e = end();
for (; it!=e; ++it )
if ( (*it)->m_name==name )
break;
return it;
}
KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name, GUIProfile prof )
: KParts::ReadOnlyPart( parent, name )
{
d = 0;
KHTMLFactory::registerPart( this );
- setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
+ setInstance( KHTMLFactory::instance(), false );
init( new KHTMLView( this, parentWidget, widgetname ), prof );
}
KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof )
: KParts::ReadOnlyPart( parent, name )
{
d = 0;
KHTMLFactory::registerPart( this );
- setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
+ setInstance( KHTMLFactory::instance(), false );
assert( view );
init( view, prof );
}
void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
{
if ( prof == DefaultGUI )
setXMLFile( "khtml.rc" );
else if ( prof == BrowserViewGUI )
setXMLFile( "khtml_browser.rc" );
d = new KHTMLPartPrivate(parent());
d->m_view = view;
setWidget( d->m_view );
d->m_guiProfile = prof;
d->m_extension = new KHTMLPartBrowserExtension( this, "KHTMLBrowserExtension" );
d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
d->m_statusBarExtension = new KParts::StatusBarExtension( this );
d->m_statusBarIconLabel = 0L;
d->m_bSecurityInQuestion = false;
d->m_paLoadImages = 0;
d->m_paDebugScript = 0;
d->m_bMousePressed = false;
d->m_bRightMousePressed = false;
d->m_paViewDocument = new KAction( i18n( "View Do&cument Source" ), CTRL + Key_U, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
d->m_paViewInfo = new KAction( i18n( "View Document Information" ), CTRL+Key_I, this, SLOT( slotViewPageInfo() ), actionCollection(), "viewPageInfo" );
d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
d->m_paSaveDocument = KStdAction::saveAs( this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
if ( parentPart() )
d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" );
d->m_paSecurity->setWhatsThis( i18n( "Security Settings
"
"Shows the certificate of the displayed page. Only "
"pages that have been transmitted using a secure, encrypted connection have a "
"certificate.
"
"Hint: If the image shows a closed lock, the page has been transmitted over a "
"secure connection.") );
d->m_paDebugRenderTree = new KAction( i18n( "Print Rendering Tree to STDOUT" ), 0, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
d->m_paDebugDOMTree = new KAction( i18n( "Print DOM Tree to STDOUT" ), 0, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
d->m_paStopAnimations = new KAction( i18n( "Stop Animated Images" ), 0, this, SLOT( slotStopAnimations() ), actionCollection(), "stopAnimations" );
d->m_paSetEncoding = new KActionMenu( i18n( "Set &Encoding" ), "charset", actionCollection(), "setEncoding" );
d->m_paSetEncoding->setDelayed( false );
d->m_automaticDetection = new KPopupMenu( 0L );
d->m_automaticDetection->insertItem( i18n( "Semi-Automatic" ), 0 );
d->m_automaticDetection->insertItem( i18n( "Arabic" ), 1 );
d->m_automaticDetection->insertItem( i18n( "Baltic" ), 2 );
d->m_automaticDetection->insertItem( i18n( "Central European" ), 3 );
//d->m_automaticDetection->insertItem( i18n( "Chinese" ), 4 );
d->m_automaticDetection->insertItem( i18n( "Greek" ), 5 );
d->m_automaticDetection->insertItem( i18n( "Hebrew" ), 6 );
d->m_automaticDetection->insertItem( i18n( "Japanese" ), 7 );
//d->m_automaticDetection->insertItem( i18n( "Korean" ), 8 );
d->m_automaticDetection->insertItem( i18n( "Russian" ), 9 );
//d->m_automaticDetection->insertItem( i18n( "Thai" ), 10 );
d->m_automaticDetection->insertItem( i18n( "Turkish" ), 11 );
d->m_automaticDetection->insertItem( i18n( "Ukrainian" ), 12 );
//d->m_automaticDetection->insertItem( i18n( "Unicode" ), 13 );
d->m_automaticDetection->insertItem( i18n( "Western European" ), 14 );
connect( d->m_automaticDetection, SIGNAL( activated( int ) ), this, SLOT( slotAutomaticDetectionLanguage( int ) ) );
d->m_paSetEncoding->popupMenu()->insertItem( i18n( "Automatic Detection" ), d->m_automaticDetection, 0 );
d->m_paSetEncoding->insert( new KActionSeparator( actionCollection() ) );
d->m_manualDetection = new KSelectAction( i18n( "short for Manual Detection", "Manual" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "manualDetection" );
QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
d->m_manualDetection->setItems( encodings );
d->m_manualDetection->setCurrentItem( -1 );
d->m_paSetEncoding->insert( d->m_manualDetection );
KConfig *config = KGlobal::config();
if ( config->hasGroup( "HTML Settings" ) ) {
config->setGroup( "HTML Settings" );
khtml::Decoder::AutoDetectLanguage language;
QCString name = QTextCodec::codecForLocale()->name();
name = name.lower();
if ( name == "cp1256" || name == "iso-8859-6" ) {
language = khtml::Decoder::Arabic;
}
else if ( name == "cp1257" || name == "iso-8859-13" || name == "iso-8859-4" ) {
language = khtml::Decoder::Baltic;
}
else if ( name == "cp1250" || name == "ibm852" || name == "iso-8859-2" || name == "iso-8859-3" ) {
language = khtml::Decoder::CentralEuropean;
}
else if ( name == "cp1251" || name == "koi8-r" || name == "iso-8859-5" ) {
language = khtml::Decoder::Russian;
}
else if ( name == "koi8-u" ) {
language = khtml::Decoder::Ukrainian;
}
else if ( name == "cp1253" || name == "iso-8859-7" ) {
language = khtml::Decoder::Greek;
}
else if ( name == "cp1255" || name == "iso-8859-8" || name == "iso-8859-8-i" ) {
language = khtml::Decoder::Hebrew;
}
else if ( name == "jis7" || name == "eucjp" || name == "sjis" ) {
language = khtml::Decoder::Japanese;
}
else if ( name == "cp1254" || name == "iso-8859-9" ) {
language = khtml::Decoder::Turkish;
}
else if ( name == "cp1252" || name == "iso-8859-1" || name == "iso-8859-15" ) {
language = khtml::Decoder::WesternEuropean;
}
else
language = khtml::Decoder::SemiautomaticDetection;
int _id = config->readNumEntry( "AutomaticDetectionLanguage", language );
d->m_automaticDetection->setItemChecked( _id, true );
d->m_paSetEncoding->popupMenu()->setItemChecked( 0, true );
d->m_autoDetectLanguage = static_cast< khtml::Decoder::AutoDetectLanguage >( _id );
}
d->m_paUseStylesheet = new KSelectAction( i18n( "Use S&tylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
if ( prof == BrowserViewGUI ) {
d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n(
"Increase Font Sizes" ), "viewmag+", "CTRL++;CTRL+=", this,
SLOT( slotIncZoomFast() ), actionCollection(), "incFontSizes" );
d->m_paIncZoomFactor->setWhatsThis( i18n( "Increase Font Size
"
"Make the font in this window bigger. "
"Click and hold down the mouse button for a menu with all available font sizes." ) );
d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n(
"Decrease Font Sizes" ), "viewmag-", CTRL + Key_Minus, this,
SLOT( slotDecZoomFast() ), actionCollection(), "decFontSizes" );
d->m_paDecZoomFactor->setWhatsThis( i18n( "Decrease Font Size
"
"Make the font in this window smaller. "
"Click and hold down the mouse button for a menu with all available font sizes." ) );
}
d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" );
d->m_paFind->setWhatsThis( i18n( "Find text
"
"Shows a dialog that allows you to find text on the displayed page." ) );
d->m_paFindNext = KStdAction::findNext( this, SLOT( slotFindNext() ), actionCollection(), "findNext" );
d->m_paFindNext->setWhatsThis( i18n( "Find next
"
"Find the next occurrence of the text that you "
"have found using the Find Text function" ) );
if ( parentPart() )
{
d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
d->m_paFindNext->setShortcut( KShortcut() ); // avoid clashes
}
d->m_paPrintFrame = new KAction( i18n( "Print Frame..." ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
d->m_paPrintFrame->setWhatsThis( i18n( "Print Frame
"
"Some pages have several frames. To print only a single frame, click "
"on it and then use this function." ) );
d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
if ( parentPart() )
d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
d->m_paToggleCaretMode = new KToggleAction(i18n("Toggle Caret Mode"),
Key_F7, this, SLOT(slotToggleCaretMode()),
actionCollection(), "caretMode");
d->m_paToggleCaretMode->setChecked(isCaretMode());
if (parentPart())
d->m_paToggleCaretMode->setShortcut(KShortcut()); // avoid clashes
// set the default java(script) flags according to the current host.
d->m_bOpenMiddleClick = d->m_settings->isOpenMiddleClickEnabled();
d->m_bBackRightClick = d->m_settings->isBackRightClickEnabled();
d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled();
setDebugScript( d->m_settings->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = d->m_settings->isJavaEnabled();
d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled();
// Set the meta-refresh flag...
d->m_metaRefreshEnabled = d->m_settings->isAutoDelayedActionsEnabled ();
connect( view, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
connect( this, SIGNAL( completed() ),
this, SLOT( updateActions() ) );
connect( this, SIGNAL( completed( bool ) ),
this, SLOT( updateActions() ) );
connect( this, SIGNAL( started( KIO::Job * ) ),
this, SLOT( updateActions() ) );
d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
connect ( &d->m_progressUpdateTimer, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
findTextBegin(); //reset find variables
connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
this, SLOT( slotRedirect() ) );
d->m_dcopobject = new KHTMLPartIface(this);
+ if ( prof == BrowserViewGUI && !parentPart() )
+ loadPlugins( partObject(), this, instance() );
+
// "khtml" catalog does not exist, our translations are in kdelibs.
// removing this catalog from KGlobal::locale() prevents problems
// with changing the language in applications at runtime -Thomas Reitelbach
KGlobal::locale()->removeCatalogue("khtml");
}
KHTMLPart::~KHTMLPart()
{
//kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
KConfig *config = KGlobal::config();
config->setGroup( "HTML Settings" );
config->writeEntry( "AutomaticDetectionLanguage", d->m_autoDetectLanguage );
delete d->m_automaticDetection;
delete d->m_manualDetection;
slotWalletClosed();
if (!parentPart()) { // only delete it if the top khtml_part closes
removeJSErrorExtension();
}
d->m_find = 0; // deleted by its parent, the view.
if ( d->m_manager )
{
d->m_manager->setActivePart( 0 );
// We specify "this" as parent qobject for d->manager, so no need to delete it.
}
stopAutoScroll();
d->m_redirectionTimer.stop();
if (!d->m_bComplete)
closeURL();
disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
clear();
if ( d->m_view )
{
d->m_view->hide();
d->m_view->viewport()->hide();
d->m_view->m_part = 0;
}
// Have to delete this here since we forward declare it in khtmlpart_p and
// at least some compilers won't call the destructor in this case.
delete d->m_jsedlg;
d->m_jsedlg = 0;
if (!parentPart()) // only delete d->m_frame if the top khtml_part closes
delete d->m_frame;
delete d; d = 0;
KHTMLFactory::deregisterPart( this );
}
bool KHTMLPart::restoreURL( const KURL &url )
{
kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
d->m_redirectionTimer.stop();
/*
* That's not a good idea as it will call closeURL() on all
* child frames, preventing them from further loading. This
* method gets called from restoreState() in case of a full frameset
* restoral, and restoreState() calls closeURL() before restoring
* anyway.
kdDebug( 6050 ) << "closing old URL" << endl;
closeURL();
*/
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
d->m_workingURL = url;
// set the java(script) flags according to the current host.
d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
m_url = url;
KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
emit started( 0L );
return true;
}
bool KHTMLPart::openURL( const KURL &url )
{
kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
d->m_redirectionTimer.stop();
// check to see if this is an "error://" URL. This is caused when an error
// occurs before this part was loaded (e.g. KonqRun), and is passed to
// khtmlpart so that it can display the error.
if ( url.protocol() == "error" && url.hasSubURL() ) {
closeURL();
if( d->m_bJScriptEnabled )
d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
/**
* The format of the error url is that two variables are passed in the query:
* error = int kio error code, errText = QString error text from kio
* and the URL where the error happened is passed as a sub URL.
*/
KURL::List urls = KURL::split( url );
//kdDebug(6050) << "Handling error URL. URL count:" << urls.count() << endl;
if ( urls.count() > 1 ) {
KURL mainURL = urls.first();
int error = mainURL.queryItem( "error" ).toInt();
// error=0 isn't a valid error code, so 0 means it's missing from the URL
if ( error == 0 ) error = KIO::ERR_UNKNOWN;
QString errorText = mainURL.queryItem( "errText", HINT_UTF8 );
urls.pop_front();
d->m_workingURL = KURL::join( urls );
//kdDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
htmlError( error, errorText, d->m_workingURL );
return true;
}
}
if (!parentPart()) { // only do it for toplevel part
QString host = url.isLocalFile() ? "localhost" : url.host();
QString userAgent = KProtocolManager::userAgentForHost(host);
if (userAgent != KProtocolManager::userAgentForHost(QString::null)) {
if (!d->m_statusBarUALabel) {
d->m_statusBarUALabel = new KURLLabel(d->m_statusBarExtension->statusBar());
d->m_statusBarUALabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
d->m_statusBarUALabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
d->m_statusBarUALabel->setUseCursor(false);
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarUALabel, 0, false);
d->m_statusBarUALabel->setPixmap(SmallIcon("agent", instance()));
} else {
QToolTip::remove(d->m_statusBarUALabel);
}
QToolTip::add(d->m_statusBarUALabel, i18n("The fake user-agent '%1' is in use.").arg(userAgent));
} else if (d->m_statusBarUALabel) {
d->m_statusBarExtension->removeStatusBarItem(d->m_statusBarUALabel);
delete d->m_statusBarUALabel;
d->m_statusBarUALabel = 0L;
}
}
KParts::URLArgs args( d->m_extension->urlArgs() );
// in case we have a) no frameset (don't test m_frames.count(), iframes get in there)
// b) the url is identical with the currently
// displayed one (except for the htmlref!) , c) the url request is not a POST
// operation and d) the caller did not request to reload the page we try to
// be smart and instead of reloading the whole document we just jump to the
// request html anchor
bool isFrameSet = false;
if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
HTMLDocumentImpl* htmlDoc = static_cast(d->m_doc);
isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
}
if ( url.hasRef() && !isFrameSet )
{
//if new url == old url, jump to anchor straight away
//no need to reload unless explicitly asked
bool noReloadForced = !args.reload && !args.redirectedRequest() && !args.doPost();
if (urlcmp( url.url(), m_url.url(), true, true ) && noReloadForced)
{
kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
m_url = url;
emit started( 0L );
if ( !gotoAnchor( url.encodedHtmlRef()) )
gotoAnchor( url.htmlRef() );
d->m_bComplete = true;
if (d->m_doc)
d->m_doc->setParsing(false);
kdDebug( 6050 ) << "completed..." << endl;
emit completed();
return true;
}
}
//jump to the anchor AFTER layouting is done, otherwise the position of the
//anchor is not known and we have no clue to which coordinates to jump
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
// Save offset of viewport when page is reloaded to be compliant
// to every other capable browser out there.
if (args.reload) {
args.xOffset = d->m_view->contentsX();
args.yOffset = d->m_view->contentsY();
d->m_extension->setURLArgs(args);
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(gotoAnchor()));
connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
}
if (!d->m_restored)
closeURL();
// 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
// data arrives) (Simon)
m_url = url;
if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
m_url.path().isEmpty()) {
m_url.setPath("/");
emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
}
// copy to m_workingURL after fixing m_url above
d->m_workingURL = m_url;
args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
args.metaData().insert("ssl_parent_ip", d->m_ssl_parent_ip);
args.metaData().insert("ssl_parent_cert", d->m_ssl_parent_cert);
args.metaData().insert("PropagateHttpHeader", "true");
args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
args.metaData().insert("ssl_activate_warnings", "TRUE" );
args.metaData().insert("cross-domain", toplevelURL().url());
if (d->m_restored)
{
args.metaData().insert("referrer", d->m_pageReferrer);
d->m_cachePolicy = KIO::CC_Cache;
}
else if (args.reload)
d->m_cachePolicy = KIO::CC_Reload;
else
d->m_cachePolicy = KProtocolManager::cacheControl();
if ( args.doPost() && (m_url.protocol().startsWith("http")) )
{
d->m_job = KIO::http_post( m_url, args.postData, false );
d->m_job->addMetaData("content-type", args.contentType() );
}
else
{
d->m_job = KIO::get( m_url, false, false );
d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
}
if (widget())
d->m_job->setWindow(widget()->topLevelWidget());
d->m_job->addMetaData(args.metaData());
connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
SLOT( slotFinished( KIO::Job* ) ) );
connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray& ) ),
SLOT( slotData( KIO::Job*, const QByteArray& ) ) );
connect ( d->m_job, SIGNAL( infoMessage( KIO::Job*, const QString& ) ),
SLOT( slotInfoMessage(KIO::Job*, const QString& ) ) );
connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL& ) ),
SLOT( slotRedirection(KIO::Job*, const KURL&) ) );
d->m_bComplete = false;
d->m_bLoadEventEmitted = false;
// delete old status bar msg's from kjs (if it _was_ activated on last URL)
if( d->m_bJScriptEnabled )
d->m_statusBarText[BarOverrideText] = d->m_statusBarText[BarDefaultText] = QString::null;
// set the javascript flags according to the current url
d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
setDebugScript( KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
connect( d->m_job, SIGNAL( result( KIO::Job* ) ),
this, SLOT( slotJobDone( KIO::Job* ) ) );
d->m_jobspeed = 0;
// If this was an explicit reload and the user style sheet should be used,
// do a stat to see whether the stylesheet was changed in the meanwhile.
if ( args.reload && !settings()->userStyleSheet().isEmpty() ) {
KURL url( settings()->userStyleSheet() );
KIO::StatJob *job = KIO::stat( url, false /* don't show progress */ );
connect( job, SIGNAL( result( KIO::Job * ) ),
this, SLOT( slotUserSheetStatDone( KIO::Job * ) ) );
}
emit started( 0L );
return true;
}
bool KHTMLPart::closeURL()
{
if ( d->m_job )
{
KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
d->m_job->kill();
d->m_job = 0;
}
if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
HTMLDocumentImpl* hdoc = static_cast( d->m_doc );
if ( hdoc->body() && d->m_bLoadEventEmitted ) {
hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
if ( d->m_doc )
d->m_doc->updateRendering();
d->m_bLoadEventEmitted = false;
}
}
d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
d->m_bLoadEventEmitted = true; // don't want that one either
d->m_cachePolicy = KProtocolManager::cacheControl(); // reset cache policy
disconnect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
KHTMLPageCache::self()->cancelFetch(this);
if ( d->m_doc && d->m_doc->parsing() )
{
kdDebug( 6050 ) << " was still parsing... calling end " << endl;
slotFinishedParsing();
d->m_doc->setParsing(false);
}
if ( !d->m_workingURL.isEmpty() )
{
// Aborted before starting to render
kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
}
d->m_workingURL = KURL();
if ( d->m_doc && d->m_doc->docLoader() )
khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
// tell all subframes to stop as well
{
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
{
if ( (*it)->m_run )
(*it)->m_run->abort();
if ( !( *it )->m_part.isNull() )
( *it )->m_part->closeURL();
}
}
// tell all objects to stop as well
{
ConstFrameIt it = d->m_objects.begin();
const ConstFrameIt end = d->m_objects.end();
for (; it != end; ++it)
{
if ( !( *it )->m_part.isNull() )
( *it )->m_part->closeURL();
}
}
// Stop any started redirections as well!! (DA)
if ( d && d->m_redirectionTimer.isActive() )
d->m_redirectionTimer.stop();
// null node activated.
emit nodeActivated(Node());
// make sure before clear() runs, we pop out of a dialog's message loop
if ( d->m_view )
d->m_view->closeChildDialogs();
return true;
}
DOM::HTMLDocument KHTMLPart::htmlDocument() const
{
if (d->m_doc && d->m_doc->isHTMLDocument())
return static_cast(d->m_doc);
else
return static_cast(0);
}
DOM::Document KHTMLPart::document() const
{
return d->m_doc;
}
KParts::BrowserExtension *KHTMLPart::browserExtension() const
{
return d->m_extension;
}
KParts::BrowserHostExtension *KHTMLPart::browserHostExtension() const
{
return d->m_hostExtension;
}
KHTMLView *KHTMLPart::view() const
{
return d->m_view;
}
void KHTMLPart::setStatusMessagesEnabled( bool enable )
{
d->m_statusMessagesEnabled = enable;
}
KJS::Interpreter *KHTMLPart::jScriptInterpreter()
{
KJSProxy *proxy = jScript();
if (!proxy || proxy->paused())
return 0;
return proxy->interpreter();
}
bool KHTMLPart::statusMessagesEnabled() const
{
return d->m_statusMessagesEnabled;
}
void KHTMLPart::setJScriptEnabled( bool enable )
{
if ( !enable && jScriptEnabled() && d->m_frame && d->m_frame->m_jscript ) {
d->m_frame->m_jscript->clear();
}
d->m_bJScriptForce = enable;
d->m_bJScriptOverride = true;
}
bool KHTMLPart::jScriptEnabled() const
{
if(onlyLocalReferences()) return false;
if ( d->m_bJScriptOverride )
return d->m_bJScriptForce;
return d->m_bJScriptEnabled;
}
void KHTMLPart::setMetaRefreshEnabled( bool enable )
{
d->m_metaRefreshEnabled = enable;
}
bool KHTMLPart::metaRefreshEnabled() const
{
return d->m_metaRefreshEnabled;
}
// Define this to disable dlopening kjs_html, when directly linking to it.
// You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
// and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
// remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
// Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
// OK - that's the default now, use the opposite of the above instructions to go back
// to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
#define DIRECT_LINKAGE_TO_ECMA
#ifdef DIRECT_LINKAGE_TO_ECMA
extern "C" { KJSProxy *kjs_html_init(khtml::ChildFrame * childframe); }
#endif
static bool createJScript(khtml::ChildFrame *frame)
{
#ifndef DIRECT_LINKAGE_TO_ECMA
KLibrary *lib = KLibLoader::self()->library("kjs_html");
if ( !lib ) {
setJScriptEnabled( false );
return false;
}
// look for plain C init function
void *sym = lib->symbol("kjs_html_init");
if ( !sym ) {
lib->unload();
setJScriptEnabled( false );
return false;
}
typedef KJSProxy* (*initFunction)(khtml::ChildFrame *);
initFunction initSym = (initFunction) sym;
frame->m_jscript = (*initSym)(d->m_frame);
frame->m_kjs_lib = lib;
#else
frame->m_jscript = kjs_html_init(frame);
// frame->m_kjs_lib remains 0L.
#endif
return true;
}
KJSProxy *KHTMLPart::jScript()
{
if (!jScriptEnabled()) return 0;
if ( !d->m_frame ) {
KHTMLPart * p = parentPart();
if (!p) {
d->m_frame = new khtml::ChildFrame;
d->m_frame->m_part = this;
} else {
ConstFrameIt it = p->d->m_frames.begin();
const ConstFrameIt end = p->d->m_frames.end();
for (; it != end; ++it)
if ((*it)->m_part.operator->() == this) {
d->m_frame = *it;
break;
}
}
if ( !d->m_frame )
return 0;
}
if ( !d->m_frame->m_jscript )
if (!createJScript(d->m_frame))
return 0;
if (d->m_bJScriptDebugEnabled)
d->m_frame->m_jscript->setDebugEnabled(true);
return d->m_frame->m_jscript;
}
QVariant KHTMLPart::crossFrameExecuteScript(const QString& target, const QString& script)
{
KHTMLPart* destpart = this;
QString trg = target.lower();
if (target == "_top") {
while (destpart->parentPart())
destpart = destpart->parentPart();
}
else if (target == "_parent") {
if (parentPart())
destpart = parentPart();
}
else if (target == "_self" || target == "_blank") {
// we always allow these
}
else {
destpart = findFrame(target);
if (!destpart)
destpart = this;
}
// easy way out?
if (destpart == this)
return executeScript(DOM::Node(), script);
// now compare the domains
if (destpart->checkFrameAccess(this))
return destpart->executeScript(DOM::Node(), script);
// eww, something went wrong. better execute it in our frame
return executeScript(DOM::Node(), script);
}
//Enable this to see all JS scripts being executed
//#define KJS_VERBOSE
KJSErrorDlg *KHTMLPart::jsErrorExtension() {
if (!d->m_settings->jsErrorsEnabled()) {
return 0L;
}
if (parentPart()) {
return parentPart()->jsErrorExtension();
}
if (!d->m_statusBarJSErrorLabel) {
d->m_statusBarJSErrorLabel = new KURLLabel(d->m_statusBarExtension->statusBar());
d->m_statusBarJSErrorLabel->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small));
d->m_statusBarJSErrorLabel->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
d->m_statusBarJSErrorLabel->setUseCursor(false);
d->m_statusBarExtension->addStatusBarItem(d->m_statusBarJSErrorLabel, 0, false);
QToolTip::add(d->m_statusBarJSErrorLabel, i18n("This web page contains coding errors."));
d->m_statusBarJSErrorLabel->setPixmap(SmallIcon("bug", instance()));
connect(d->m_statusBarJSErrorLabel, SIGNAL(leftClickedURL()), SLOT(launchJSErrorDialog()));
connect(d->m_statusBarJSErrorLabel, SIGNAL(rightClickedURL()), SLOT(jsErrorDialogContextMenu()));
}
if (!d->m_jsedlg) {
d->m_jsedlg = new KJSErrorDlg;
d->m_jsedlg->setURL(m_url.prettyURL());
if (KGlobalSettings::showIconsOnPushButtons()) {
d->m_jsedlg->_clear->setIconSet(SmallIconSet("locationbar_erase"));
d->m_jsedlg->_close->setIconSet(SmallIconSet("fileclose"));
}
}
return d->m_jsedlg;
}
void KHTMLPart::removeJSErrorExtension() {
if (parentPart()) {
parentPart()->removeJSErrorExtension();
return;
}
if (d->m_statusBarJSErrorLabel != 0) {
d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarJSErrorLabel );
delete d->m_statusBarJSErrorLabel;
d->m_statusBarJSErrorLabel = 0;
}
delete d->m_jsedlg;
d->m_jsedlg = 0;
}
void KHTMLPart::disableJSErrorExtension() {
removeJSErrorExtension();
// These two lines are really kind of hacky, and it sucks to do this inside
// KHTML but I don't know of anything that's reasonably easy as an alternative
// right now. It makes me wonder if there should be a more clean way to
// contact all running "KHTML" instance as opposed to Konqueror instances too.
d->m_settings->setJSErrorsEnabled(false);
DCOPClient::mainClient()->send("konqueror*", "KonquerorIface", "reparseConfiguration()", QByteArray());
}
void KHTMLPart::jsErrorDialogContextMenu() {
KPopupMenu *m = new KPopupMenu(0L);
m->insertItem(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
m->insertItem(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
m->popup(QCursor::pos());
}
void KHTMLPart::launchJSErrorDialog() {
KJSErrorDlg *dlg = jsErrorExtension();
if (dlg) {
dlg->show();
dlg->raise();
}
}
QVariant KHTMLPart::executeScript(const QString& filename, int baseLine, const DOM::Node& n, const QString& script)
{
#ifdef KJS_VERBOSE
// The script is now printed by KJS's Parser::parse
kdDebug(6070) << "executeScript: caller='" << name() << "' filename=" << filename << " baseLine=" << baseLine /*<< " script=" << script*/ << endl;
#endif
KJSProxy *proxy = jScript();
if (!proxy || proxy->paused())
return QVariant();
KJS::Completion comp;
QVariant ret = proxy->evaluate(filename, baseLine, script, n, &comp);
/*
* Error handling
*/
if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
KJSErrorDlg *dlg = jsErrorExtension();
if (dlg) {
KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
dlg->addError(i18n("Error: %1: %2").arg(filename, msg.qstring()));
}
}
return ret;
}
QVariant KHTMLPart::executeScript( const QString &script )
{
return executeScript( DOM::Node(), script );
}
QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script )
{
#ifdef KJS_VERBOSE
kdDebug(6070) << "KHTMLPart::executeScript caller='" << name() << "' node=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " /* << script */ << endl;
#endif
KJSProxy *proxy = jScript();
if (!proxy || proxy->paused())
return QVariant();
++(d->m_runningScripts);
KJS::Completion comp;
const QVariant ret = proxy->evaluate( QString::null, 1, script, n, &comp );
--(d->m_runningScripts);
/*
* Error handling
*/
if (comp.complType() == KJS::Throw && !comp.value().isNull()) {
KJSErrorDlg *dlg = jsErrorExtension();
if (dlg) {
KJS::UString msg = comp.value().toString(proxy->interpreter()->globalExec());
dlg->addError(i18n("Error: node %1: %2").arg(n.nodeName().string()).arg(msg.qstring()));
}
}
if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
submitFormAgain();
#ifdef KJS_VERBOSE
kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
#endif
return ret;
}
bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
{
//kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
d->scheduledScript = script;
d->scheduledScriptNode = n;
return true;
}
QVariant KHTMLPart::executeScheduledScript()
{
if( d->scheduledScript.isEmpty() )
return QVariant();
//kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
d->scheduledScript = QString();
d->scheduledScriptNode = DOM::Node();
return ret;
}
void KHTMLPart::setJavaEnabled( bool enable )
{
d->m_bJavaForce = enable;
d->m_bJavaOverride = true;
}
bool KHTMLPart::javaEnabled() const
{
if (onlyLocalReferences()) return false;
#ifndef Q_WS_QWS
if( d->m_bJavaOverride )
return d->m_bJavaForce;
return d->m_bJavaEnabled;
#else
return false;
#endif
}
KJavaAppletContext *KHTMLPart::javaContext()
{
return 0;
}
KJavaAppletContext *KHTMLPart::createJavaContext()
{
return 0;
}
void KHTMLPart::setPluginsEnabled( bool enable )
{
d->m_bPluginsForce = enable;
d->m_bPluginsOverride = true;
}
bool KHTMLPart::pluginsEnabled() const
{
if (onlyLocalReferences()) return false;
if ( d->m_bPluginsOverride )
return d->m_bPluginsForce;
return d->m_bPluginsEnabled;
}
static int s_DOMTreeIndentLevel = 0;
void KHTMLPart::slotDebugDOMTree()
{
if ( d->m_doc && d->m_doc->firstChild() )
qDebug("%s", d->m_doc->firstChild()->toString().string().latin1());
// Now print the contents of the frames that contain HTML
const int indentLevel = s_DOMTreeIndentLevel++;
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for (; it != end; ++it )
if ( !( *it )->m_part.isNull() && (*it)->m_part->inherits( "KHTMLPart" ) ) {
KParts::ReadOnlyPart* const p = ( *it )->m_part;
kdDebug(6050) << QString().leftJustify(s_DOMTreeIndentLevel*4,' ') << "FRAME " << p->name() << " " << endl;
static_cast( p )->slotDebugDOMTree();
}
s_DOMTreeIndentLevel = indentLevel;
}
void KHTMLPart::slotDebugScript()
{
if (jScript())
jScript()->showDebugWindow();
}
void KHTMLPart::slotDebugRenderTree()
{
#ifndef NDEBUG
if ( d->m_doc ) {
d->m_doc->renderer()->printTree();
// dump out the contents of the rendering & DOM trees
// QString dumps;
// QTextStream outputStream(dumps,IO_WriteOnly);
// d->m_doc->renderer()->layer()->dump( outputStream );
// kdDebug() << "dump output:" << "\n" + dumps;
}
#endif
}
void KHTMLPart::slotStopAnimations()
{
stopAnimations();
}
void KHTMLPart::setAutoloadImages( bool enable )
{
if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
return;
if ( d->m_doc )
d->m_doc->docLoader()->setAutoloadImages( enable );
unplugActionList( "loadImages" );
if ( enable ) {
delete d->m_paLoadImages;
d->m_paLoadImages = 0;
}
else if ( !d->m_paLoadImages )
d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
if ( d->m_paLoadImages ) {
QPtrList lst;
lst.append( d->m_paLoadImages );
plugActionList( "loadImages", lst );
}
}
bool KHTMLPart::autoloadImages() const
{
if ( d->m_doc )
return d->m_doc->docLoader()->autoloadImages();
return true;
}
void KHTMLPart::clear()
{
if ( d->m_bCleared )
return;
d->m_bCleared = true;
d->m_bClearing = true;
{
ConstFrameIt it = d->m_frames.begin();
const ConstFrameIt end = d->m_frames.end();
for(; it != end; ++it )
{
// Stop HTMLRun jobs for frames
if ( (*it)->m_run )
(*it)->m_run->abort();
}
}
{
ConstFrameIt it = d->m_objects.begin();
const ConstFrameIt end = d->m_objects.end();
for(; it != end; ++it )
{
// Stop HTMLRun jobs for objects
if ( (*it)->m_run )
(*it)->m_run->abort();
}
}
findTextBegin(); // resets d->m_findNode and d->m_findPos
d->m_mousePressNode = DOM::Node();
if ( d->m_doc )
d->m_doc->detach();
// Moving past doc so that onUnload works.
if ( d->m_frame && d->m_frame->m_jscript )
d->m_frame->m_jscript->clear();
// stopping marquees
if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->layer())
d->m_doc->renderer()->layer()->suspendMarquees();
if ( d->m_view )
d->m_view->clear();
// do not dereference the document before the jscript and view are cleared, as some destructors
// might still try to access the document.
if ( d->m_doc ) {
d->m_doc->deref();
}
d->m_doc = 0;
delete d->m_decoder;
d->m_decoder = 0;
// We don't want to change between parts if we are going to delete all of them anyway
disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
if (d->m_frames.count())
{
KHTMLFrameList frames = d->m_frames;
d->m_frames.clear();
ConstFrameIt it = frames.begin();
const ConstFrameIt end = frames.end();
for(; it != end; ++it )
{
if ( (*it)->m_part )
{
partManager()->removePart( (*it)->m_part );
delete (KParts::ReadOnlyPart *)(*it)->m_part;
}
delete *it;
}
}
if (d->m_objects.count())
{
KHTMLFrameList objects = d->m_objects;
d->m_objects.clear();
ConstFrameIt oi = objects.begin();
const ConstFrameIt oiEnd = objects.end();
for (; oi != oiEnd; ++oi )
delete *oi;
}
// Listen to part changes again
connect( partManager(), SIGNAL( activePartChanged( KParts::Part * ) ),
this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
d->m_delayRedirect = 0;
d->m_redirectURL = QString::null;
d->m_redirectionTimer.stop();
d->m_redirectLockHistory = true;
d->m_bClearing = false;
d->m_frameNameId = 1;
d->m_bFirstData = true;
d->m_bMousePressed = false;
d->m_selectionStart = DOM::Node();
d->m_selectionEnd = DOM::Node();
d->m_startOffset = 0;
d->m_endOffset = 0;
#ifndef QT_NO_CLIPBOARD
connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
#endif
d->m_jobPercent = 0;
if ( !d->m_haveEncoding )
d->m_encoding = QString::null;
#ifdef SPEED_DEBUG
d->m_parsetime.restart();
#endif
}
bool KHTMLPart::openFile()
{
return true;
}
DOM::HTMLDocumentImpl *KHTMLPart::docImpl() const
{
if ( d && d->m_doc && d->m_doc->isHTMLDocument() )
return static_cast(d->m_doc);
return 0;
}
DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
{
if ( d )
return d->m_doc;
return 0;
}
void KHTMLPart::slotInfoMessage(KIO::Job* kio_job, const QString& msg)
{
assert(d->m_job == kio_job);
if (!parentPart())
setStatusBarText(msg, BarDefaultText);
}
void KHTMLPart::setPageSecurity( PageSecurity sec )
{
if ( sec != NotCrypted && !d->m_statusBarIconLabel && !parentPart() ) {
d->m_statusBarIconLabel = new KURLLabel( d->m_statusBarExtension->statusBar() );
d->m_statusBarIconLabel->setFixedHeight( instance()->iconLoader()->currentSize(KIcon::Small) );
d->m_statusBarIconLabel->setSizePolicy(QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ));
d->m_statusBarIconLabel->setUseCursor( false );
d->m_statusBarExtension->addStatusBarItem( d->m_statusBarIconLabel, 0, false );
connect( d->m_statusBarIconLabel, SIGNAL( leftClickedURL() ), SLOT( slotSecurity() ) );
} else if (d->m_statusBarIconLabel) {
QToolTip::remove(d->m_statusBarIconLabel);
}
if (d->m_statusBarIconLabel) {
if (d->m_ssl_in_use)
QToolTip::add(d->m_statusBarIconLabel,
i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
else QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
}
QString iconName;
switch (sec) {
case NotCrypted:
iconName = "decrypted";
if ( d->m_statusBarIconLabel ) {
d->m_statusBarExtension->removeStatusBarItem( d->m_statusBarIconLabel );
delete d->m_statusBarIconLabel;
d->m_statusBarIconLabel = 0L;
}
break;
case Encrypted:
iconName = "encrypted";
break;
case Mixed:
iconName = "halfencrypted";
break;
}
d->m_paSecurity->setIcon( iconName );
if ( d->m_statusBarIconLabel )
d->m_statusBarIconLabel->setPixmap( SmallIcon( iconName, instance() ) );
}
void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
{
assert ( d->m_job == kio_job );
//kdDebug( 6050 ) << "slotData: " << data.size() << endl;
// The first data ?
if ( !d->m_workingURL.isEmpty() )
{
//kdDebug( 6050 ) << "begin!" << endl;
// We must suspend KIO while we're inside begin() because it can cause
// crashes if a window (such as kjsdebugger) goes back into the event loop,
// more data arrives, and begin() gets called again (re-entered).
d->m_job->suspend();
begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
d->m_job->resume();
if (d->m_cachePolicy == KIO::CC_Refresh)
d->m_doc->docLoader()->setCachePolicy(KIO::CC_Verify);
else
d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
d->m_workingURL = KURL();
d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
// When the first data arrives, the metadata has just been made available
d->m_httpHeaders = d->m_job->queryMetaData("HTTP-Headers");
time_t cacheCreationDate = d->m_job->queryMetaData("cache-creation-date").toLong();
d->m_doc->docLoader()->setCacheCreationDate(cacheCreationDate);
d->m_pageServices = d->m_job->queryMetaData("PageServices");
d->m_pageReferrer = d->m_job->queryMetaData("referrer");
d->m_bSecurityInQuestion = false;
d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
{
KHTMLPart *p = parentPart();
if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
while (p->parentPart()) p = p->parentPart();
p->setPageSecurity( Mixed );
p->d->m_bSecurityInQuestion = true;
}
}
setPageSecurity( d->m_ssl_in_use ? Encrypted : NotCrypted );
// Shouldn't all of this be done only if ssl_in_use == true ? (DF)
d->m_ssl_parent_ip = d->m_job->queryMetaData("ssl_parent_ip");
d->m_ssl_parent_cert = d->m_job->queryMetaData("ssl_parent_cert");
d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
if (d->m_statusBarIconLabel) {
QToolTip::remove(d->m_statusBarIconLabel);
if (d->m_ssl_in_use) {
QToolTip::add(d->m_statusBarIconLabel, i18n("Session is secured with %1 bit %2.").arg(d->m_ssl_cipher_used_bits).arg(d->m_ssl_cipher));
} else {
QToolTip::add(d->m_statusBarIconLabel, i18n("Session is not secured."));
}
}
// Check for charset meta-data
QString qData = d->m_job->queryMetaData("charset");
if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
d->m_encoding = qData;
// Support for http-refresh
qData = d->m_job->queryMetaData("http-refresh");
if( !qData.isEmpty())
d->m_doc->processHttpEquiv("refresh", qData);
// Support Content-Location per section 14.14 of RFC 2616.
QString baseURL = d->m_job->queryMetaData ("content-location");
if (!baseURL.isEmpty())
d->m_doc->setBaseURL(KURL( d->m_doc->completeURL(baseURL) ));
if ( !m_url.isLocalFile() ) {
// Support for http last-modified
d->m_lastModified = d->m_job->queryMetaData("modified");
} else
d->m_lastModified = QString::null; // done on-demand by lastModified()
// Reset contents position
connect(d->m_view, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
}
KHTMLPageCache::self()->addData(d->m_cacheId, data);
write( data.data(), data.size() );
if (d->m_frame && d->m_frame->m_jscript)
d->m_frame->m_jscript->dataReceived();
}
void KHTMLPart::slotRestoreData(const QByteArray &data )
{
// The first data ?
if ( !d->m_workingURL.isEmpty() )
{
long saveCacheId = d->m_cacheId;
QString savePageReferrer = d->m_pageReferrer;
begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
d->m_pageReferrer = savePageReferrer;
d->m_cacheId = saveCacheId;
d->m_workingURL = KURL();
}
//kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
write( data.data(), data.size() );
if (data.size() == 0)
{
//kdDebug( 6050 ) << "slotRestoreData: <>" << endl;
// End of data.
if (d->m_doc && d->m_doc->parsing())
end(); //will emit completed()
}
}
void KHTMLPart::showError( KIO::Job* job )
{
kdDebug(6050) << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
<< " d->m_bCleared=" << d->m_bCleared << endl;
if (job->error() == KIO::ERR_NO_CONTENT)
return;
if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
job->showErrorDialog( /*d->m_view*/ );
else
{
htmlError( job->error(), job->errorText(), d->m_workingURL );
}
}
// This is a protected method, placed here because of it's relevance to showError
void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
{
kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
// make sure we're not executing any embedded JS
bool bJSFO = d->m_bJScriptForce;
bool bJSOO = d->m_bJScriptOverride;
d->m_bJScriptForce = false;
d->m_bJScriptOverride = true;
begin();
QString errText = QString::fromLatin1( "" )
.arg(QApplication::reverseLayout() ? "rtl" : "ltr");
errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
errText += QString::fromLatin1( "