1 /* This file is part of the KDE project
3 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
4 * 1999 Lars Knoll <knoll@kde.org>
5 * 1999 Antti Koivisto <koivisto@kde.org>
6 * 2000 Simon Hausmann <hausmann@kde.org>
7 * 2000 Stefan Schimanski <1Stein@gmx.de>
8 * 2001-2005 George Staikos <staikos@kde.org>
9 * 2001-2003 Dirk Mueller <mueller@kde.org>
10 * 2000-2005 David Faure <faure@kde.org>
11 * 2002 Apple Computer, Inc.
13 * This library is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Library General Public
15 * License as published by the Free Software Foundation; either
16 * version 2 of the License, or (at your option) any later version.
18 * This library is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public License
24 * along with this library; see the file COPYING.LIB. If not, write to
25 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26 * Boston, MA 02110-1301, USA.
30 #include "khtml_part.h"
32 #include "ui_htmlpageinfo.h"
34 #include "khtmlviewbar.h"
35 #include "khtml_pagecache.h"
37 #include "dom/dom_string.h"
38 #include "dom/dom_element.h"
39 #include "dom/dom_exception.h"
40 #include "dom/html_document.h"
41 #include "dom/dom2_range.h"
42 #include "dom/html_document.h"
43 #include "editing/editor.h"
44 #include "editing/htmlediting.h"
45 #include "html/html_documentimpl.h"
46 #include "html/html_baseimpl.h"
47 #include "html/html_objectimpl.h"
48 #include "html/html_miscimpl.h"
49 #include "html/html_imageimpl.h"
50 #include "rendering/render_text.h"
51 #include "rendering/render_frames.h"
52 #include "rendering/render_layer.h"
53 #include "misc/htmlhashes.h"
54 #include "misc/loader.h"
55 #include "misc/khtml_partaccessor.h"
56 #include "xml/dom2_eventsimpl.h"
57 #include "xml/dom2_rangeimpl.h"
58 #include "xml/xml_tokenizer.h"
59 #include "css/cssstyleselector.h"
60 #include "css/csshelper.h"
63 #include "khtmlview.h"
64 #include <kparts/partmanager.h>
65 #include "ecma/kjs_proxy.h"
66 #include "ecma/kjs_window.h"
67 #include "khtml_settings.h"
68 #include "kjserrordlg.h"
70 #include <kjs/function.h>
71 #include <kjs/interpreter.h>
73 #include <sys/types.h>
79 #include <kstandarddirs.h>
80 #include <kstringhandler.h>
82 #include <kio/jobuidelegate.h>
83 #include <kio/global.h>
84 #include <kio/netaccess.h>
85 #include <kio/hostinfo_p.h>
86 #include <kprotocolmanager.h>
89 #include <kiconloader.h>
91 #include <kmessagebox.h>
92 #include <kstandardaction.h>
93 #include <kactioncollection.h>
94 #include <kfiledialog.h>
95 #include <kmimetypetrader.h>
96 #include <ktemporaryfile.h>
97 #include <kglobalsettings.h>
98 #include <ktoolinvocation.h>
99 #include <kauthorized.h>
100 #include <kparts/browserinterface.h>
101 #include <kde_file.h>
102 #include <kactionmenu.h>
103 #include <ktoggleaction.h>
104 #include <kcodecaction.h>
105 #include <kselectaction.h>
107 #include <ksslinfodialog.h>
109 #include <kfileitem.h>
110 #include <kurifilter.h>
111 #include <kstatusbar.h>
112 #include <kurllabel.h>
114 #include <QtGui/QClipboard>
115 #include <QtCore/QFile>
116 #include <QtCore/QMetaEnum>
117 #include <QtGui/QTextDocument>
118 #include <QtCore/QDate>
119 #include <QtNetwork/QSslCertificate>
121 #include "khtmlpart_p.h"
122 #include "khtml_iface.h"
123 #include "kpassivepopup.h"
125 #include "rendering/render_form.h"
126 #include <kwindowsystem.h>
127 #include <kconfiggroup.h>
129 #include "ecma/debugger/debugwindow.h"
132 #include <svg/SVGDocument.h>
134 bool KHTMLPartPrivate::s_dnsInitialised
= false;
136 // DNS prefetch settings
137 static const int sMaxDNSPrefetchPerPage
= 42;
138 static const int sDNSPrefetchTimerDelay
= 200;
139 static const int sDNSTTLSeconds
= 400;
140 static const int sDNSCacheSize
= 500;
145 class PartStyleSheetLoader
: public CachedObjectClient
148 PartStyleSheetLoader(KHTMLPart
*part
, DOM::DOMString url
, DocLoader
* dl
)
151 m_cachedSheet
= dl
->requestStyleSheet(url
, QString(), "text/css",
152 true /* "user sheet" */);
154 m_cachedSheet
->ref( this );
156 virtual ~PartStyleSheetLoader()
158 if ( m_cachedSheet
) m_cachedSheet
->deref(this);
160 virtual void setStyleSheet(const DOM::DOMString
&, const DOM::DOMString
&sheet
, const DOM::DOMString
&, const DOM::DOMString
&/*mimetype*/)
163 m_part
->setUserStyleSheet( sheet
.string() );
167 virtual void error( int, const QString
& ) {
170 QPointer
<KHTMLPart
> m_part
;
171 khtml::CachedCSSStyleSheet
*m_cachedSheet
;
175 void khtml::ChildFrame::liveConnectEvent(const unsigned long, const QString
& event
, const KParts::LiveConnectExtension::ArgList
& args
)
177 if (!m_part
|| !m_partContainerElement
|| !m_liveconnect
)
182 script
.sprintf("%s(", event
.toLatin1().constData());
184 KParts::LiveConnectExtension::ArgList::const_iterator i
= args
.begin();
185 const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin
= i
;
186 const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd
= args
.end();
188 for ( ; i
!= argsEnd
; ++i
) {
191 if ((*i
).first
== KParts::LiveConnectExtension::TypeString
) {
193 script
+= QString((*i
).second
).replace('\\', "\\\\").replace('"', "\\\"");
196 script
+= (*i
).second
;
199 kDebug(6050) << script
;
201 KHTMLPart
* part
= qobject_cast
<KHTMLPart
*>(m_part
->parent());
205 part
->framejScript(m_part
);
207 // we have a jscript => a part in an iframe
209 m_jscript
->evaluate(QString(), 1, script
, 0L, &cmp
);
211 part
->executeScript(DOM::Node(m_partContainerElement
), script
);
214 KHTMLFrameList::Iterator
KHTMLFrameList::find( const QString
&name
)
216 Iterator it
= begin();
217 const Iterator e
= end();
220 if ( (*it
)->m_name
==name
)
226 KHTMLPart::KHTMLPart( QWidget
*parentWidget
, QObject
*parent
, GUIProfile prof
)
227 : KParts::ReadOnlyPart( parent
)
230 KHTMLGlobal::registerPart( this );
231 setComponentData( KHTMLGlobal::componentData(), false );
232 init( new KHTMLView( this, parentWidget
), prof
);
235 KHTMLPart::KHTMLPart( KHTMLView
*view
, QObject
*parent
, GUIProfile prof
)
236 : KParts::ReadOnlyPart( parent
)
239 KHTMLGlobal::registerPart( this );
240 setComponentData( KHTMLGlobal::componentData(), false );
243 view
->setPart( this );
247 void KHTMLPart::init( KHTMLView
*view
, GUIProfile prof
)
249 if ( prof
== DefaultGUI
)
250 setXMLFile( "khtml.rc" );
251 else if ( prof
== BrowserViewGUI
)
252 setXMLFile( "khtml_browser.rc" );
254 d
= new KHTMLPartPrivate(this, parent());
259 QWidget
*widget
= new QWidget( view
->parentWidget() );
260 QVBoxLayout
*layout
= new QVBoxLayout( widget
);
261 layout
->setContentsMargins( 0, 0, 0, 0 );
262 layout
->setSpacing( 0 );
263 widget
->setLayout( layout
);
265 d
->m_topViewBar
= new KHTMLViewBar( KHTMLViewBar::Top
, d
->m_view
, widget
);
266 d
->m_bottomViewBar
= new KHTMLViewBar( KHTMLViewBar::Bottom
, d
->m_view
, widget
);
268 layout
->addWidget( d
->m_topViewBar
);
269 layout
->addWidget( d
->m_view
);
270 layout
->addWidget( d
->m_bottomViewBar
);
272 widget
->setFocusProxy( d
->m_view
);
277 d
->m_guiProfile
= prof
;
278 d
->m_extension
= new KHTMLPartBrowserExtension( this );
279 d
->m_extension
->setObjectName( "KHTMLBrowserExtension" );
280 d
->m_hostExtension
= new KHTMLPartBrowserHostExtension( this );
281 d
->m_statusBarExtension
= new KParts::StatusBarExtension( this );
282 d
->m_statusBarPopupLabel
= 0L;
283 d
->m_openableSuppressedPopups
= 0;
285 d
->m_paLoadImages
= 0;
286 d
->m_paDebugScript
= 0;
287 d
->m_bMousePressed
= false;
288 d
->m_bRightMousePressed
= false;
289 d
->m_bCleared
= false;
291 if ( prof
== BrowserViewGUI
) {
292 d
->m_paViewDocument
= new KAction( i18n( "View Do&cument Source" ), this );
293 actionCollection()->addAction( "viewDocumentSource", d
->m_paViewDocument
);
294 d
->m_paViewDocument
->setShortcut( QKeySequence(Qt::CTRL
+ Qt::Key_U
) );
295 connect( d
->m_paViewDocument
, SIGNAL( triggered( bool ) ), this, SLOT( slotViewDocumentSource() ) );
297 d
->m_paViewFrame
= new KAction( i18n( "View Frame Source" ), this );
298 actionCollection()->addAction( "viewFrameSource", d
->m_paViewFrame
);
299 connect( d
->m_paViewFrame
, SIGNAL( triggered( bool ) ), this, SLOT( slotViewFrameSource() ) );
301 d
->m_paViewInfo
= new KAction( i18n( "View Document Information" ), this );
302 actionCollection()->addAction( "viewPageInfo", d
->m_paViewInfo
);
303 d
->m_paViewInfo
->setShortcut( QKeySequence(Qt::CTRL
+Qt::Key_I
) );
304 connect( d
->m_paViewInfo
, SIGNAL( triggered( bool ) ), this, SLOT( slotViewPageInfo() ) );
306 d
->m_paSaveBackground
= new KAction( i18n( "Save &Background Image As..." ), this );
307 actionCollection()->addAction( "saveBackground", d
->m_paSaveBackground
);
308 connect( d
->m_paSaveBackground
, SIGNAL( triggered( bool ) ), this, SLOT( slotSaveBackground() ) );
310 d
->m_paSaveDocument
= actionCollection()->addAction( KStandardAction::SaveAs
, "saveDocument",
311 this, SLOT( slotSaveDocument() ) );
313 d
->m_paSaveDocument
->setShortcuts( KShortcut() ); // avoid clashes
315 d
->m_paSaveFrame
= new KAction( i18n( "Save &Frame As..." ), this );
316 actionCollection()->addAction( "saveFrame", d
->m_paSaveFrame
);
317 connect( d
->m_paSaveFrame
, SIGNAL( triggered( bool ) ), this, SLOT( slotSaveFrame() ) );
319 d
->m_paViewDocument
= 0;
320 d
->m_paViewFrame
= 0;
322 d
->m_paSaveBackground
= 0;
323 d
->m_paSaveDocument
= 0;
324 d
->m_paSaveFrame
= 0;
327 d
->m_paSecurity
= new KAction( i18n( "SSL" ), this );
328 actionCollection()->addAction( "security", d
->m_paSecurity
);
329 connect( d
->m_paSecurity
, SIGNAL( triggered( bool ) ), this, SLOT( slotSecurity() ) );
331 d
->m_paDebugRenderTree
= new KAction( i18n( "Print Rendering Tree to STDOUT" ), this );
332 actionCollection()->addAction( "debugRenderTree", d
->m_paDebugRenderTree
);
333 connect( d
->m_paDebugRenderTree
, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugRenderTree() ) );
335 d
->m_paDebugDOMTree
= new KAction( i18n( "Print DOM Tree to STDOUT" ), this );
336 actionCollection()->addAction( "debugDOMTree", d
->m_paDebugDOMTree
);
337 connect( d
->m_paDebugDOMTree
, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugDOMTree() ) );
339 d
->m_paStopAnimations
= new KAction( i18n( "Stop Animated Images" ), this );
340 actionCollection()->addAction( "stopAnimations", d
->m_paStopAnimations
);
341 connect( d
->m_paStopAnimations
, SIGNAL( triggered( bool ) ), this, SLOT( slotStopAnimations() ) );
343 d
->m_paSetEncoding
= new KCodecAction( KIcon("character-set"), i18n( "Set &Encoding" ), this, true );
344 actionCollection()->addAction( "setEncoding", d
->m_paSetEncoding
);
345 // d->m_paSetEncoding->setDelayed( false );
347 connect( d
->m_paSetEncoding
, SIGNAL(triggered(const QString
&)), this, SLOT( slotSetEncoding(const QString
&)));
348 connect( d
->m_paSetEncoding
, SIGNAL(triggered(KEncodingDetector::AutoDetectScript
)), this, SLOT( slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript
)));
350 if ( KGlobal::config()->hasGroup( "HTML Settings" ) ) {
351 KConfigGroup
config( KGlobal::config(), "HTML Settings" );
353 d
->m_autoDetectLanguage
= static_cast<KEncodingDetector::AutoDetectScript
>(config
.readEntry( "AutomaticDetectionLanguage", /*static_cast<int>(language) */0));
354 if (d
->m_autoDetectLanguage
==KEncodingDetector::None
) {
355 const QByteArray name
= KGlobal::locale()->encoding().toLower();
356 // kWarning() << "00000000 ";
357 if (name
.endsWith("1251")||name
.startsWith("koi")||name
=="iso-8859-5")
358 d
->m_autoDetectLanguage
=KEncodingDetector::Cyrillic
;
359 else if (name
.endsWith("1256")||name
=="iso-8859-6")
360 d
->m_autoDetectLanguage
=KEncodingDetector::Arabic
;
361 else if (name
.endsWith("1257")||name
=="iso-8859-13"||name
=="iso-8859-4")
362 d
->m_autoDetectLanguage
=KEncodingDetector::Baltic
;
363 else if (name
.endsWith("1250")|| name
=="ibm852" || name
=="iso-8859-2" || name
=="iso-8859-3" )
364 d
->m_autoDetectLanguage
=KEncodingDetector::CentralEuropean
;
365 else if (name
.endsWith("1253")|| name
=="iso-8859-7" )
366 d
->m_autoDetectLanguage
=KEncodingDetector::Greek
;
367 else if (name
.endsWith("1255")|| name
=="iso-8859-8" || name
=="iso-8859-8-i" )
368 d
->m_autoDetectLanguage
=KEncodingDetector::Hebrew
;
369 else if (name
=="jis7" || name
=="eucjp" || name
=="sjis" )
370 d
->m_autoDetectLanguage
=KEncodingDetector::Japanese
;
371 else if (name
.endsWith("1254")|| name
=="iso-8859-9" )
372 d
->m_autoDetectLanguage
=KEncodingDetector::Turkish
;
373 else if (name
.endsWith("1252")|| name
=="iso-8859-1" || name
=="iso-8859-15" )
374 d
->m_autoDetectLanguage
=KEncodingDetector::WesternEuropean
;
376 d
->m_autoDetectLanguage
=KEncodingDetector::SemiautomaticDetection
;
377 // kWarning() << "0000000end " << d->m_autoDetectLanguage << " " << KGlobal::locale()->encodingMib();
379 d
->m_paSetEncoding
->setCurrentAutoDetectScript(d
->m_autoDetectLanguage
);
382 d
->m_paUseStylesheet
= new KSelectAction( i18n( "Use S&tylesheet"), this );
383 actionCollection()->addAction( "useStylesheet", d
->m_paUseStylesheet
);
384 connect( d
->m_paUseStylesheet
, SIGNAL( triggered( int ) ), this, SLOT( slotUseStylesheet() ) );
386 if ( prof
== BrowserViewGUI
) {
387 d
->m_paIncZoomFactor
= new KHTMLZoomFactorAction( this, true, "format-font-size-more", i18n( "Enlarge Font" ), this );
388 actionCollection()->addAction( "incFontSizes", d
->m_paIncZoomFactor
);
389 connect(d
->m_paIncZoomFactor
, SIGNAL(triggered(bool)), SLOT( slotIncFontSizeFast() ));
390 d
->m_paIncZoomFactor
->setWhatsThis( i18n( "Enlarge Font<br /><br />"
391 "Make the font in this window bigger. "
392 "Click and hold down the mouse button for a menu with all available font sizes." ) );
394 d
->m_paDecZoomFactor
= new KHTMLZoomFactorAction( this, false, "format-font-size-less", i18n( "Shrink Font" ), this );
395 actionCollection()->addAction( "decFontSizes", d
->m_paDecZoomFactor
);
396 connect(d
->m_paDecZoomFactor
, SIGNAL(triggered(bool)), SLOT( slotDecFontSizeFast() ));
397 d
->m_paDecZoomFactor
->setWhatsThis( i18n( "Shrink Font<br /><br />"
398 "Make the font in this window smaller. "
399 "Click and hold down the mouse button for a menu with all available font sizes." ) );
401 // For framesets, this action also affects frames, so only
402 // the frameset needs to define a shortcut for the action.
404 // TODO: Why also CTRL+=? Because of http://trolltech.com/developer/knowledgebase/524/?
405 // Nobody else does it...
406 d
->m_paIncZoomFactor
->setShortcut( KShortcut("CTRL++; CTRL+=") );
407 d
->m_paDecZoomFactor
->setShortcut( QKeySequence(Qt::CTRL
+ Qt::Key_Minus
) );
411 d
->m_paFind
= actionCollection()->addAction( KStandardAction::Find
, "find", this, SLOT( slotFind() ) );
412 d
->m_paFind
->setWhatsThis( i18n( "Find text<br /><br />"
413 "Shows a dialog that allows you to find text on the displayed page." ) );
415 d
->m_paFindNext
= actionCollection()->addAction( KStandardAction::FindNext
, "findNext", this, SLOT( slotFindNext() ) );
416 d
->m_paFindNext
->setWhatsThis( i18n( "Find next<br /><br />"
417 "Find the next occurrence of the text that you "
418 "have found using the <b>Find Text</b> function" ) );
420 d
->m_paFindPrev
= actionCollection()->addAction( KStandardAction::FindPrev
, "findPrevious",
421 this, SLOT( slotFindPrev() ) );
422 d
->m_paFindPrev
->setWhatsThis( i18n( "Find previous<br /><br />"
423 "Find the previous occurrence of the text that you "
424 "have found using the <b>Find Text</b> function" ) );
426 d
->m_paFindAheadText
= new KAction( i18n("Find Text as You Type"), this );
427 actionCollection()->addAction( "findAheadText", d
->m_paFindAheadText
);
428 d
->m_paFindAheadText
->setShortcuts( KShortcut( '/' ) );
429 connect( d
->m_paFindAheadText
, SIGNAL( triggered( bool ) ), this, SLOT( slotFindAheadText()) );
431 d
->m_paFindAheadLinks
= new KAction( i18n("Find Links as You Type"), this );
432 actionCollection()->addAction( "findAheadLink", d
->m_paFindAheadLinks
);
433 d
->m_paFindAheadLinks
->setShortcuts( KShortcut( '\'' ) );
434 connect( d
->m_paFindAheadLinks
, SIGNAL( triggered( bool ) ), this, SLOT( slotFindAheadLink() ) );
436 d
->m_paFindAheadText
->setEnabled( false );
437 d
->m_paFindAheadLinks
->setEnabled( false );
441 d
->m_paFind
->setShortcuts( KShortcut() ); // avoid clashes
442 d
->m_paFindNext
->setShortcuts( KShortcut() ); // avoid clashes
443 d
->m_paFindPrev
->setShortcuts( KShortcut() ); // avoid clashes
444 d
->m_paFindAheadText
->setShortcuts( KShortcut());
445 d
->m_paFindAheadLinks
->setShortcuts( KShortcut());
448 d
->m_paPrintFrame
= new KAction( i18n( "Print Frame..." ), this );
449 actionCollection()->addAction( "printFrame", d
->m_paPrintFrame
);
450 d
->m_paPrintFrame
->setIcon( KIcon( "document-print-frame" ) );
451 connect( d
->m_paPrintFrame
, SIGNAL( triggered( bool ) ), this, SLOT( slotPrintFrame() ) );
452 d
->m_paPrintFrame
->setWhatsThis( i18n( "Print Frame<br /><br />"
453 "Some pages have several frames. To print only a single frame, click "
454 "on it and then use this function." ) );
456 // Warning: The name selectAll is used hardcoded by some 3rd parties to remove the
457 // shortcut for selectAll so they do not get ambigous shortcuts. Renaming it
458 // will either crash or render useless that workaround. It would be better
459 // to use the name KStandardAction::name(KStandardAction::SelectAll) but we
460 // can't for the same reason.
461 d
->m_paSelectAll
= actionCollection()->addAction( KStandardAction::SelectAll
, "selectAll",
462 this, SLOT( slotSelectAll() ) );
463 d
->m_paSelectAll
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
465 d
->m_paSelectAll
->setShortcuts( KShortcut() ); // avoid clashes
467 d
->m_paToggleCaretMode
= new KToggleAction(i18n("Toggle Caret Mode"), this );
468 actionCollection()->addAction( "caretMode", d
->m_paToggleCaretMode
);
469 d
->m_paToggleCaretMode
->setShortcut( QKeySequence(Qt::Key_F7
) );
470 connect( d
->m_paToggleCaretMode
, SIGNAL( triggered( bool ) ), this, SLOT(slotToggleCaretMode()) );
471 d
->m_paToggleCaretMode
->setChecked(isCaretMode());
473 d
->m_paToggleCaretMode
->setShortcut(KShortcut()); // avoid clashes
475 // set the default java(script) flags according to the current host.
476 d
->m_bOpenMiddleClick
= d
->m_settings
->isOpenMiddleClickEnabled();
477 d
->m_bBackRightClick
= d
->m_settings
->isBackRightClickEnabled();
478 d
->m_bJScriptEnabled
= d
->m_settings
->isJavaScriptEnabled();
479 setDebugScript( d
->m_settings
->isJavaScriptDebugEnabled() );
480 d
->m_bJavaEnabled
= d
->m_settings
->isJavaEnabled();
481 d
->m_bPluginsEnabled
= d
->m_settings
->isPluginsEnabled();
483 // Set the meta-refresh flag...
484 d
->m_metaRefreshEnabled
= d
->m_settings
->isAutoDelayedActionsEnabled ();
486 KHTMLSettings::KSmoothScrollingMode ssm
= d
->m_settings
->smoothScrolling();
487 if (ssm
== KHTMLSettings::KSmoothScrollingDisabled
)
488 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled
);
489 else if (ssm
== KHTMLSettings::KSmoothScrollingWhenEfficient
)
490 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient
);
492 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled
);
494 if (d
->m_bDNSPrefetchIsDefault
&& !onlyLocalReferences()) {
495 KHTMLSettings::KDNSPrefetch dpm
= d
->m_settings
->dnsPrefetch();
496 if (dpm
== KHTMLSettings::KDNSPrefetchDisabled
)
497 d
->m_bDNSPrefetch
= DNSPrefetchDisabled
;
498 else if (dpm
== KHTMLSettings::KDNSPrefetchOnlyWWWAndSLD
)
499 d
->m_bDNSPrefetch
= DNSPrefetchOnlyWWWAndSLD
;
501 d
->m_bDNSPrefetch
= DNSPrefetchEnabled
;
504 if (!KHTMLPartPrivate::s_dnsInitialised
&& d
->m_bDNSPrefetch
!= DNSPrefetchDisabled
) {
505 KIO::HostInfo::setCacheSize( sDNSCacheSize
);
506 KIO::HostInfo::setTTL( sDNSTTLSeconds
);
507 KHTMLPartPrivate::s_dnsInitialised
= true;
510 actionCollection()->associateWidget(view
);
512 connect( view
, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
514 connect( this, SIGNAL( completed() ),
515 this, SLOT( updateActions() ) );
516 connect( this, SIGNAL( completed( bool ) ),
517 this, SLOT( updateActions() ) );
518 connect( this, SIGNAL( started( KIO::Job
* ) ),
519 this, SLOT( updateActions() ) );
521 connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ),
522 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ) );
523 connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader
*, khtml::CachedObject
*) ),
524 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
525 connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader
*, khtml::CachedObject
*) ),
526 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
528 connect ( &d
->m_progressUpdateTimer
, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
530 findTextBegin(); //reset find variables
532 connect( &d
->m_redirectionTimer
, SIGNAL( timeout() ),
533 this, SLOT( slotRedirect() ) );
535 if (QDBusConnection::sessionBus().isConnected()) {
536 new KHTMLPartIface(this); // our "adaptor"
537 for (int i
= 1; ; ++i
)
538 if (QDBusConnection::sessionBus().registerObject(QString("/KHTML/%1/widget").arg(i
), this))
540 else if (i
== 0xffff)
541 kFatal() << "Something is very wrong in KHTMLPart!";
544 if (prof
== BrowserViewGUI
&& !parentPart())
547 // "khtml" catalog does not exist, our translations are in kdelibs.
548 // removing this catalog from KGlobal::locale() prevents problems
549 // with changing the language in applications at runtime -Thomas Reitelbach
550 // DF: a better fix would be to set the right catalog name in the KComponentData!
551 KGlobal::locale()->removeCatalog("khtml");
554 KHTMLPart::~KHTMLPart()
556 kDebug(6050) << this;
557 KConfigGroup
config( KGlobal::config(), "HTML Settings" );
558 config
.writeEntry( "AutomaticDetectionLanguage", int(d
->m_autoDetectLanguage
) );
561 if (!parentPart()) { // only delete it if the top khtml_part closes
562 removeJSErrorExtension();
563 delete d
->m_statusBarPopupLabel
;
568 d
->m_manager
->setActivePart( 0 );
569 // We specify "this" as parent qobject for d->manager, so no need to delete it.
573 d
->m_redirectionTimer
.stop();
578 disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ),
579 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ) );
580 disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader
*, khtml::CachedObject
*) ),
581 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
582 disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader
*, khtml::CachedObject
*) ),
583 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
590 d
->m_view
->viewport()->hide();
591 d
->m_view
->m_part
= 0;
594 // Have to delete this here since we forward declare it in khtmlpart_p and
595 // at least some compilers won't call the destructor in this case.
599 if (!parentPart()) // only delete d->m_frame if the top khtml_part closes
602 KHTMLGlobal::deregisterPart( this );
605 bool KHTMLPart::restoreURL( const KUrl
&url
)
607 kDebug( 6050 ) << url
;
609 d
->m_redirectionTimer
.stop();
612 * That's not a good idea as it will call closeUrl() on all
613 * child frames, preventing them from further loading. This
614 * method gets called from restoreState() in case of a full frameset
615 * restoral, and restoreState() calls closeUrl() before restoring
617 kDebug( 6050 ) << "closing old URL";
621 d
->m_bComplete
= false;
622 d
->m_bLoadEventEmitted
= false;
623 d
->m_workingURL
= url
;
625 // set the java(script) flags according to the current host.
626 d
->m_bJScriptEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaScriptEnabled(url
.host());
627 setDebugScript( KHTMLGlobal::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
628 d
->m_bJavaEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaEnabled(url
.host());
629 d
->m_bPluginsEnabled
= KHTMLGlobal::defaultHTMLSettings()->isPluginsEnabled(url
.host());
633 d
->m_restoreScrollPosition
= true;
634 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
635 connect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
637 KHTMLPageCache::self()->fetchData( d
->m_cacheId
, this, SLOT(slotRestoreData(const QByteArray
&)));
644 bool KHTMLPartPrivate::isLocalAnchorJump( const KUrl
& url
)
646 return url
.hasRef() && urlcmp( url
.url(), q
->url().url(),
647 KUrl::CompareWithoutTrailingSlash
| KUrl::CompareWithoutFragment
);
650 void KHTMLPartPrivate::executeAnchorJump( const KUrl
& url
, bool lockHistory
)
652 // Note: we want to emit openUrlNotify first thing, to make the history capture the old state.
654 emit m_extension
->openUrlNotify();
656 if ( !q
->gotoAnchor( url
.encodedHtmlRef()) )
657 q
->gotoAnchor( url
.htmlRef() );
660 emit m_extension
->setLocationBarUrl( url
.prettyUrl() );
663 bool KHTMLPart::openUrl( const KUrl
&url
)
665 kDebug( 6050 ) << this << "opening" << url
;
667 d
->m_redirectionTimer
.stop();
669 // check to see if this is an "error://" URL. This is caused when an error
670 // occurs before this part was loaded (e.g. KonqRun), and is passed to
671 // khtmlpart so that it can display the error.
672 if ( url
.protocol() == "error" && url
.hasSubUrl() ) {
675 if( d
->m_bJScriptEnabled
) {
676 d
->m_statusBarText
[BarOverrideText
].clear();
677 d
->m_statusBarText
[BarDefaultText
].clear();
681 * The format of the error url is that two variables are passed in the query:
682 * error = int kio error code, errText = QString error text from kio
683 * and the URL where the error happened is passed as a sub URL.
685 KUrl::List urls
= KUrl::split( url
);
686 //kDebug(6050) << "Handling error URL. URL count:" << urls.count();
688 if ( urls
.count() > 1 ) {
689 KUrl mainURL
= urls
.first();
690 int error
= mainURL
.queryItem( "error" ).toInt();
691 // error=0 isn't a valid error code, so 0 means it's missing from the URL
692 if ( error
== 0 ) error
= KIO::ERR_UNKNOWN
;
693 QString errorText
= mainURL
.queryItem( "errText" );
695 d
->m_workingURL
= KUrl::join( urls
);
696 //kDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyUrl();
697 emit d
->m_extension
->setLocationBarUrl( d
->m_workingURL
.prettyUrl() );
698 htmlError( error
, errorText
, d
->m_workingURL
);
703 if (!parentPart()) { // only do it for toplevel part
704 QString host
= url
.isLocalFile() ? "localhost" : url
.host();
705 QString userAgent
= KProtocolManager::userAgentForHost(host
);
706 if (userAgent
!= KProtocolManager::userAgentForHost(QString())) {
707 if (!d
->m_statusBarUALabel
) {
708 d
->m_statusBarUALabel
= new KUrlLabel(d
->m_statusBarExtension
->statusBar());
709 d
->m_statusBarUALabel
->setFixedHeight(KHTMLGlobal::iconLoader()->currentSize(KIconLoader::Small
));
710 d
->m_statusBarUALabel
->setSizePolicy(QSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
));
711 d
->m_statusBarUALabel
->setUseCursor(false);
712 d
->m_statusBarExtension
->addStatusBarItem(d
->m_statusBarUALabel
, 0, false);
713 d
->m_statusBarUALabel
->setPixmap(SmallIcon("preferences-web-browser-identification"));
715 d
->m_statusBarUALabel
->setToolTip(i18n("The fake user-agent '%1' is in use.", userAgent
));
716 } else if (d
->m_statusBarUALabel
) {
717 d
->m_statusBarExtension
->removeStatusBarItem(d
->m_statusBarUALabel
);
718 delete d
->m_statusBarUALabel
;
719 d
->m_statusBarUALabel
= 0L;
723 KParts::BrowserArguments
browserArgs( d
->m_extension
->browserArguments() );
724 KParts::OpenUrlArguments
args( arguments() );
727 // a) we have no frameset (don't test m_frames.count(), iframes get in there)
728 // b) the url is identical with the currently displayed one (except for the htmlref!)
729 // c) the url request is not a POST operation and
730 // d) the caller did not request to reload the page
731 // e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi)
732 // => we don't reload the whole document and
733 // we just jump to the requested html anchor
734 bool isFrameSet
= false;
735 if ( d
->m_doc
&& d
->m_doc
->isHTMLDocument() ) {
736 HTMLDocumentImpl
* htmlDoc
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
737 isFrameSet
= htmlDoc
->body() && (htmlDoc
->body()->id() == ID_FRAMESET
);
740 if (isFrameSet
&& d
->isLocalAnchorJump(url
) && browserArgs
.softReload
)
742 QList
<khtml::ChildFrame
*>::Iterator it
= d
->m_frames
.begin();
743 const QList
<khtml::ChildFrame
*>::Iterator end
= d
->m_frames
.end();
744 for (; it
!= end
; ++it
) {
745 KHTMLPart
* const part
= qobject_cast
<KHTMLPart
*>( (*it
)->m_part
);
748 // We are reloading frames to make them jump into offsets.
749 KParts::OpenUrlArguments
partargs( part
->arguments() );
750 partargs
.setReload( true );
751 part
->setArguments( partargs
);
753 part
->openUrl( part
->url() );
759 if ( url
.hasRef() && !isFrameSet
)
761 bool noReloadForced
= !args
.reload() && !browserArgs
.redirectedRequest() && !browserArgs
.doPost();
762 if ( noReloadForced
&& d
->isLocalAnchorJump(url
) )
764 kDebug( 6050 ) << "jumping to anchor. m_url = " << url
;
768 if ( !gotoAnchor( url
.encodedHtmlRef()) )
769 gotoAnchor( url
.htmlRef() );
771 d
->m_bComplete
= true;
773 d
->m_doc
->setParsing(false);
775 kDebug( 6050 ) << "completed...";
781 // Save offset of viewport when page is reloaded to be compliant
782 // to every other capable browser out there.
784 args
.setXOffset( d
->m_view
->contentsX() );
785 args
.setYOffset( d
->m_view
->contentsY() );
792 d
->m_restoreScrollPosition
= d
->m_restored
;
793 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
794 connect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
796 // 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
797 // data arrives) (Simon)
798 d
->m_workingURL
= url
;
799 if(url
.protocol().startsWith( "http" ) && !url
.host().isEmpty() &&
800 url
.path().isEmpty()) {
801 d
->m_workingURL
.setPath("/");
802 emit d
->m_extension
->setLocationBarUrl( d
->m_workingURL
.prettyUrl() );
804 setUrl(d
->m_workingURL
);
806 QMap
<QString
,QString
>& metaData
= args
.metaData();
807 metaData
.insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
808 metaData
.insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
809 metaData
.insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
810 metaData
.insert("PropagateHttpHeader", "true");
811 metaData
.insert("ssl_was_in_use", d
->m_ssl_in_use
? "TRUE" : "FALSE" );
812 metaData
.insert("ssl_activate_warnings", "TRUE" );
813 metaData
.insert("cross-domain", toplevelURL().url());
817 metaData
.insert("referrer", d
->m_pageReferrer
);
818 d
->m_cachePolicy
= KIO::CC_Cache
;
820 else if (args
.reload())
821 d
->m_cachePolicy
= KIO::CC_Reload
;
823 d
->m_cachePolicy
= KProtocolManager::cacheControl();
825 if ( browserArgs
.doPost() && (url
.protocol().startsWith("http")) )
827 d
->m_job
= KIO::http_post( url
, browserArgs
.postData
, KIO::HideProgressInfo
);
828 d
->m_job
->addMetaData("content-type", browserArgs
.contentType() );
832 d
->m_job
= KIO::get( url
, KIO::NoReload
, KIO::HideProgressInfo
);
833 d
->m_job
->addMetaData("cache", KIO::getCacheControlString(d
->m_cachePolicy
));
837 d
->m_job
->ui()->setWindow(widget()->topLevelWidget());
838 d
->m_job
->addMetaData(metaData
);
840 connect( d
->m_job
, SIGNAL( result( KJob
* ) ),
841 SLOT( slotFinished( KJob
* ) ) );
842 connect( d
->m_job
, SIGNAL( data( KIO::Job
*, const QByteArray
& ) ),
843 SLOT( slotData( KIO::Job
*, const QByteArray
& ) ) );
844 connect ( d
->m_job
, SIGNAL( infoMessage( KJob
*, const QString
&, const QString
& ) ),
845 SLOT( slotInfoMessage(KJob
*, const QString
& ) ) );
846 connect( d
->m_job
, SIGNAL(redirection(KIO::Job
*, const KUrl
& ) ),
847 SLOT( slotRedirection(KIO::Job
*, const KUrl
&) ) );
849 d
->m_bComplete
= false;
850 d
->m_bLoadEventEmitted
= false;
852 // delete old status bar msg's from kjs (if it _was_ activated on last URL)
853 if( d
->m_bJScriptEnabled
) {
854 d
->m_statusBarText
[BarOverrideText
].clear();
855 d
->m_statusBarText
[BarDefaultText
].clear();
858 // set the javascript flags according to the current url
859 d
->m_bJScriptEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaScriptEnabled(url
.host());
860 setDebugScript( KHTMLGlobal::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
861 d
->m_bJavaEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaEnabled(url
.host());
862 d
->m_bPluginsEnabled
= KHTMLGlobal::defaultHTMLSettings()->isPluginsEnabled(url
.host());
865 connect( d
->m_job
, SIGNAL( speed( KJob
*, unsigned long ) ),
866 this, SLOT( slotJobSpeed( KJob
*, unsigned long ) ) );
868 connect( d
->m_job
, SIGNAL( percent( KJob
*, unsigned long ) ),
869 this, SLOT( slotJobPercent( KJob
*, unsigned long ) ) );
871 connect( d
->m_job
, SIGNAL( result( KJob
* ) ),
872 this, SLOT( slotJobDone( KJob
* ) ) );
876 // If this was an explicit reload and the user style sheet should be used,
877 // do a stat to see whether the stylesheet was changed in the meanwhile.
878 if ( args
.reload() && !settings()->userStyleSheet().isEmpty() ) {
879 KUrl
url( settings()->userStyleSheet() );
880 KIO::StatJob
*job
= KIO::stat( url
, KIO::HideProgressInfo
);
881 connect( job
, SIGNAL( result( KJob
* ) ),
882 this, SLOT( slotUserSheetStatDone( KJob
* ) ) );
884 startingJob( d
->m_job
);
890 bool KHTMLPart::closeUrl()
894 KHTMLPageCache::self()->cancelEntry(d
->m_cacheId
);
899 if ( d
->m_doc
&& d
->m_doc
->isHTMLDocument() ) {
900 HTMLDocumentImpl
* hdoc
= static_cast<HTMLDocumentImpl
*>( d
->m_doc
);
902 if ( hdoc
->body() && d
->m_bLoadEventEmitted
) {
903 hdoc
->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT
, false, false );
905 d
->m_doc
->updateRendering();
906 d
->m_bLoadEventEmitted
= false;
910 d
->m_bComplete
= true; // to avoid emitting completed() in slotFinishedParsing() (David)
911 d
->m_bLoadEventEmitted
= true; // don't want that one either
912 d
->m_cachePolicy
= KProtocolManager::cacheControl(); // reset cache policy
914 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
916 KHTMLPageCache::self()->cancelFetch(this);
917 if ( d
->m_doc
&& d
->m_doc
->parsing() )
919 kDebug( 6050 ) << " was still parsing... calling end ";
920 slotFinishedParsing();
921 d
->m_doc
->setParsing(false);
924 if ( !d
->m_workingURL
.isEmpty() )
926 // Aborted before starting to render
927 kDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << url().prettyUrl();
928 emit d
->m_extension
->setLocationBarUrl( url().prettyUrl() );
931 d
->m_workingURL
= KUrl();
933 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
934 khtml::Cache::loader()->cancelRequests( d
->m_doc
->docLoader() );
936 // tell all subframes to stop as well
938 ConstFrameIt it
= d
->m_frames
.constBegin();
939 const ConstFrameIt end
= d
->m_frames
.constEnd();
940 for (; it
!= end
; ++it
)
943 (*it
)->m_run
->abort();
944 if ( !( *it
)->m_part
.isNull() )
945 ( *it
)->m_part
->closeUrl();
948 // tell all objects to stop as well
950 ConstFrameIt it
= d
->m_objects
.constBegin();
951 const ConstFrameIt end
= d
->m_objects
.constEnd();
952 for (; it
!= end
; ++it
)
954 if ( !( *it
)->m_part
.isNull() )
955 ( *it
)->m_part
->closeUrl();
958 // Stop any started redirections as well!! (DA)
959 if ( d
&& d
->m_redirectionTimer
.isActive() )
960 d
->m_redirectionTimer
.stop();
962 // null node activated.
963 emit
nodeActivated(Node());
965 // make sure before clear() runs, we pop out of a dialog's message loop
967 d
->m_view
->closeChildDialogs();
972 DOM::HTMLDocument
KHTMLPart::htmlDocument() const
974 if (d
->m_doc
&& d
->m_doc
->isHTMLDocument())
975 return static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
977 return static_cast<HTMLDocumentImpl
*>(0);
980 DOM::Document
KHTMLPart::document() const
985 QString
KHTMLPart::documentSource() const
988 if ( !( url().isLocalFile() ) && KHTMLPageCache::self()->isComplete( d
->m_cacheId
) )
990 QByteArray sourceArray
;
991 QDataStream
dataStream( &sourceArray
, QIODevice::WriteOnly
);
992 KHTMLPageCache::self()->saveData( d
->m_cacheId
, &dataStream
);
993 QTextStream
stream( sourceArray
, QIODevice::ReadOnly
);
994 stream
.setCodec( QTextCodec::codecForName( encoding().toLatin1().constData() ) );
995 sourceStr
= stream
.readAll();
999 if( KIO::NetAccess::download( url(), tmpFile
, NULL
) )
1002 if ( f
.open( QIODevice::ReadOnly
) )
1004 QTextStream
stream( &f
);
1005 stream
.setCodec( QTextCodec::codecForName( encoding().toLatin1().constData() ) );
1006 sourceStr
= stream
.readAll();
1009 KIO::NetAccess::removeTempFile( tmpFile
);
1017 KParts::BrowserExtension
*KHTMLPart::browserExtension() const
1019 return d
->m_extension
;
1022 KParts::BrowserHostExtension
*KHTMLPart::browserHostExtension() const
1024 return d
->m_hostExtension
;
1027 KHTMLView
*KHTMLPart::view() const
1032 KHTMLViewBar
*KHTMLPart::pTopViewBar() const
1034 if (const_cast<KHTMLPart
*>(this)->parentPart())
1035 return const_cast<KHTMLPart
*>(this)->parentPart()->pTopViewBar();
1036 return d
->m_topViewBar
;
1039 KHTMLViewBar
*KHTMLPart::pBottomViewBar() const
1041 if (const_cast<KHTMLPart
*>(this)->parentPart())
1042 return const_cast<KHTMLPart
*>(this)->parentPart()->pBottomViewBar();
1043 return d
->m_bottomViewBar
;
1046 void KHTMLPart::setStatusMessagesEnabled( bool enable
)
1048 d
->m_statusMessagesEnabled
= enable
;
1051 KJS::Interpreter
*KHTMLPart::jScriptInterpreter()
1053 KJSProxy
*proxy
= jScript();
1054 if (!proxy
|| proxy
->paused())
1057 return proxy
->interpreter();
1060 bool KHTMLPart::statusMessagesEnabled() const
1062 return d
->m_statusMessagesEnabled
;
1065 void KHTMLPart::setJScriptEnabled( bool enable
)
1067 if ( !enable
&& jScriptEnabled() && d
->m_frame
&& d
->m_frame
->m_jscript
) {
1068 d
->m_frame
->m_jscript
->clear();
1070 d
->m_bJScriptForce
= enable
;
1071 d
->m_bJScriptOverride
= true;
1074 bool KHTMLPart::jScriptEnabled() const
1076 if(onlyLocalReferences()) return false;
1078 if ( d
->m_bJScriptOverride
)
1079 return d
->m_bJScriptForce
;
1080 return d
->m_bJScriptEnabled
;
1083 void KHTMLPart::setDNSPrefetch( DNSPrefetch pmode
)
1085 d
->m_bDNSPrefetch
= pmode
;
1086 d
->m_bDNSPrefetchIsDefault
= false;
1089 KHTMLPart::DNSPrefetch
KHTMLPart::dnsPrefetch() const
1091 if (onlyLocalReferences())
1092 return DNSPrefetchDisabled
;
1093 return d
->m_bDNSPrefetch
;
1096 void KHTMLPart::setMetaRefreshEnabled( bool enable
)
1098 d
->m_metaRefreshEnabled
= enable
;
1101 bool KHTMLPart::metaRefreshEnabled() const
1103 return d
->m_metaRefreshEnabled
;
1106 // Define this to disable dlopening kjs_html, when directly linking to it.
1107 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
1108 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
1109 // remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
1110 // Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
1111 // OK - that's the default now, use the opposite of the above instructions to go back
1112 // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
1113 #define DIRECT_LINKAGE_TO_ECMA
1115 #ifdef DIRECT_LINKAGE_TO_ECMA
1116 extern "C" { KJSProxy
*kjs_html_init(khtml::ChildFrame
* childframe
); }
1119 static bool createJScript(khtml::ChildFrame
*frame
)
1121 #ifndef DIRECT_LINKAGE_TO_ECMA
1122 KLibrary
*lib
= KLibLoader::self()->library(QLatin1String("kjs_html"));
1124 setJScriptEnabled( false );
1127 // look for plain C init function
1128 void *sym
= lib
->symbol("kjs_html_init");
1131 setJScriptEnabled( false );
1134 typedef KJSProxy
* (*initFunction
)(khtml::ChildFrame
*);
1135 initFunction initSym
= (initFunction
) sym
;
1136 frame
->m_jscript
= (*initSym
)(d
->m_frame
);
1137 frame
->m_kjs_lib
= lib
;
1139 frame
->m_jscript
= kjs_html_init(frame
);
1144 KJSProxy
*KHTMLPart::jScript()
1146 if (!jScriptEnabled()) return 0;
1148 if ( !d
->m_frame
) {
1149 KHTMLPart
* p
= parentPart();
1151 d
->m_frame
= new khtml::ChildFrame
;
1152 d
->m_frame
->m_part
= this;
1154 ConstFrameIt it
= p
->d
->m_frames
.constBegin();
1155 const ConstFrameIt end
= p
->d
->m_frames
.constEnd();
1156 for (; it
!= end
; ++it
)
1157 if ((*it
)->m_part
.operator->() == this) {
1165 if ( !d
->m_frame
->m_jscript
)
1166 if (!createJScript(d
->m_frame
))
1168 d
->m_frame
->m_jscript
->setDebugEnabled(d
->m_bJScriptDebugEnabled
);
1170 return d
->m_frame
->m_jscript
;
1173 QVariant
KHTMLPart::crossFrameExecuteScript(const QString
& target
, const QString
& script
)
1175 KHTMLPart
* destpart
= this;
1177 QString trg
= target
.toLower();
1179 if (target
== "_top") {
1180 while (destpart
->parentPart())
1181 destpart
= destpart
->parentPart();
1183 else if (target
== "_parent") {
1185 destpart
= parentPart();
1187 else if (target
== "_self" || target
== "_blank") {
1188 // we always allow these
1191 destpart
= findFrame(target
);
1197 if (destpart
== this)
1198 return executeScript(DOM::Node(), script
);
1200 // now compare the domains
1201 if (destpart
->checkFrameAccess(this))
1202 return destpart
->executeScript(DOM::Node(), script
);
1204 // eww, something went wrong. better execute it in our frame
1205 return executeScript(DOM::Node(), script
);
1208 //Enable this to see all JS scripts being executed
1209 //#define KJS_VERBOSE
1211 KJSErrorDlg
*KHTMLPart::jsErrorExtension() {
1212 if (!d
->m_settings
->jsErrorsEnabled()) {
1217 return parentPart()->jsErrorExtension();
1220 if (!d
->m_statusBarJSErrorLabel
) {
1221 d
->m_statusBarJSErrorLabel
= new KUrlLabel(d
->m_statusBarExtension
->statusBar());
1222 d
->m_statusBarJSErrorLabel
->setFixedHeight(KIconLoader::global()->currentSize(KIconLoader::Small
));
1223 d
->m_statusBarJSErrorLabel
->setSizePolicy(QSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
));
1224 d
->m_statusBarJSErrorLabel
->setUseCursor(false);
1225 d
->m_statusBarExtension
->addStatusBarItem(d
->m_statusBarJSErrorLabel
, 0, false);
1226 d
->m_statusBarJSErrorLabel
->setToolTip(i18n("This web page contains coding errors."));
1227 d
->m_statusBarJSErrorLabel
->setPixmap(SmallIcon("script-error"));
1228 connect(d
->m_statusBarJSErrorLabel
, SIGNAL(leftClickedUrl()), SLOT(launchJSErrorDialog()));
1229 connect(d
->m_statusBarJSErrorLabel
, SIGNAL(rightClickedUrl()), SLOT(jsErrorDialogContextMenu()));
1232 d
->m_jsedlg
= new KJSErrorDlg
;
1233 d
->m_jsedlg
->setURL(url().prettyUrl());
1234 if (KGlobalSettings::showIconsOnPushButtons()) {
1235 d
->m_jsedlg
->_clear
->setIcon(KIcon("edit-clear-locationbar-ltr"));
1236 d
->m_jsedlg
->_close
->setIcon(KIcon("window-close"));
1242 void KHTMLPart::removeJSErrorExtension() {
1244 parentPart()->removeJSErrorExtension();
1247 if (d
->m_statusBarJSErrorLabel
!= 0) {
1248 d
->m_statusBarExtension
->removeStatusBarItem( d
->m_statusBarJSErrorLabel
);
1249 delete d
->m_statusBarJSErrorLabel
;
1250 d
->m_statusBarJSErrorLabel
= 0;
1256 void KHTMLPart::disableJSErrorExtension() {
1257 removeJSErrorExtension();
1258 // These two lines are really kind of hacky, and it sucks to do this inside
1259 // KHTML but I don't know of anything that's reasonably easy as an alternative
1260 // right now. It makes me wonder if there should be a more clean way to
1261 // contact all running "KHTML" instance as opposed to Konqueror instances too.
1262 d
->m_settings
->setJSErrorsEnabled(false);
1263 emit
configurationChanged();
1266 void KHTMLPart::jsErrorDialogContextMenu() {
1267 KMenu
*m
= new KMenu(0L);
1268 m
->addAction(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
1269 m
->addAction(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
1270 m
->popup(QCursor::pos());
1273 void KHTMLPart::launchJSErrorDialog() {
1274 KJSErrorDlg
*dlg
= jsErrorExtension();
1281 void KHTMLPart::launchJSConfigDialog() {
1283 args
<< "khtml_java_js";
1284 KToolInvocation::kdeinitExec( "kcmshell4", args
);
1287 QVariant
KHTMLPart::executeScript(const QString
& filename
, int baseLine
, const DOM::Node
& n
, const QString
& script
)
1290 // The script is now printed by KJS's Parser::parse
1291 kDebug(6070) << "executeScript: caller='" << objectName() << "' filename=" << filename
<< " baseLine=" << baseLine
/*<< " script=" << script*/;
1293 KJSProxy
*proxy
= jScript();
1295 if (!proxy
|| proxy
->paused())
1298 //Make sure to initialize the interpreter before creating Completion
1299 (void)proxy
->interpreter();
1301 KJS::Completion comp
;
1303 QVariant ret
= proxy
->evaluate(filename
, baseLine
, script
, n
, &comp
);
1308 if (comp
.complType() == KJS::Throw
&& comp
.value()) {
1309 KJSErrorDlg
*dlg
= jsErrorExtension();
1311 QString msg
= KJSDebugger::DebugWindow::exceptionToString(
1312 proxy
->interpreter()->globalExec(), comp
.value());
1313 dlg
->addError(i18n("<qt><b>Error</b>: %1: %2</qt>",
1314 Qt::escape(filename
), Qt::escape(msg
)));
1318 // Handle immediate redirects now (e.g. location='foo')
1319 if ( !d
->m_redirectURL
.isEmpty() && d
->m_delayRedirect
== -1 )
1321 kDebug(6070) << "executeScript done, handling immediate redirection NOW";
1322 // Must abort tokenizer, no further script must execute.
1323 khtml::Tokenizer
* t
= d
->m_doc
->tokenizer();
1326 d
->m_redirectionTimer
.setSingleShot( true );
1327 d
->m_redirectionTimer
.start( 0 );
1333 QVariant
KHTMLPart::executeScript( const QString
&script
)
1335 return executeScript( DOM::Node(), script
);
1338 QVariant
KHTMLPart::executeScript( const DOM::Node
&n
, const QString
&script
)
1341 kDebug(6070) << "caller=" << objectName() << "node=" << n
.nodeName().string().toLatin1().constData() << "(" << (n
.isNull() ? 0 : n
.nodeType()) << ") " /* << script */;
1343 KJSProxy
*proxy
= jScript();
1345 if (!proxy
|| proxy
->paused())
1347 (void)proxy
->interpreter();//Make sure stuff is initialized
1349 ++(d
->m_runningScripts
);
1350 KJS::Completion comp
;
1351 const QVariant ret
= proxy
->evaluate( QString(), 1, script
, n
, &comp
);
1352 --(d
->m_runningScripts
);
1357 if (comp
.complType() == KJS::Throw
&& !comp
.value()) {
1358 KJSErrorDlg
*dlg
= jsErrorExtension();
1360 QString msg
= KJSDebugger::DebugWindow::exceptionToString(
1361 proxy
->interpreter()->globalExec(), comp
.value());
1362 dlg
->addError(i18n("<qt><b>Error</b>: node %1: %2</qt>",
1363 n
.nodeName().string(), Qt::escape(msg
)));
1367 if (!d
->m_runningScripts
&& d
->m_doc
&& !d
->m_doc
->parsing() && d
->m_submitForm
)
1371 kDebug(6070) << "done";
1376 void KHTMLPart::setJavaEnabled( bool enable
)
1378 d
->m_bJavaForce
= enable
;
1379 d
->m_bJavaOverride
= true;
1382 bool KHTMLPart::javaEnabled() const
1384 if (onlyLocalReferences()) return false;
1387 if( d
->m_bJavaOverride
)
1388 return d
->m_bJavaForce
;
1389 return d
->m_bJavaEnabled
;
1395 void KHTMLPart::setPluginsEnabled( bool enable
)
1397 d
->m_bPluginsForce
= enable
;
1398 d
->m_bPluginsOverride
= true;
1401 bool KHTMLPart::pluginsEnabled() const
1403 if (onlyLocalReferences()) return false;
1405 if ( d
->m_bPluginsOverride
)
1406 return d
->m_bPluginsForce
;
1407 return d
->m_bPluginsEnabled
;
1410 static int s_DOMTreeIndentLevel
= 0;
1412 void KHTMLPart::slotDebugDOMTree()
1415 qDebug("%s", d
->m_doc
->toString().string().toLatin1().constData());
1417 // Now print the contents of the frames that contain HTML
1419 const int indentLevel
= s_DOMTreeIndentLevel
++;
1421 ConstFrameIt it
= d
->m_frames
.constBegin();
1422 const ConstFrameIt end
= d
->m_frames
.constEnd();
1423 for (; it
!= end
; ++it
)
1424 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
1425 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
1426 kDebug(6050) << QString().leftJustified(s_DOMTreeIndentLevel
*4,' ') << "FRAME " << p
->objectName() << " ";
1427 static_cast<KHTMLPart
*>( p
)->slotDebugDOMTree();
1429 s_DOMTreeIndentLevel
= indentLevel
;
1432 void KHTMLPart::slotDebugScript()
1435 jScript()->showDebugWindow();
1438 void KHTMLPart::slotDebugRenderTree()
1442 d
->m_doc
->renderer()->printTree();
1443 // dump out the contents of the rendering & DOM trees
1445 // QTextStream outputStream(dumps,QIODevice::WriteOnly);
1446 // d->m_doc->renderer()->layer()->dump( outputStream );
1447 // kDebug() << "dump output:" << "\n" + dumps;
1452 void KHTMLPart::slotStopAnimations()
1457 void KHTMLPart::setAutoloadImages( bool enable
)
1459 if ( d
->m_doc
&& d
->m_doc
->docLoader()->autoloadImages() == enable
)
1463 d
->m_doc
->docLoader()->setAutoloadImages( enable
);
1465 unplugActionList( "loadImages" );
1468 delete d
->m_paLoadImages
;
1469 d
->m_paLoadImages
= 0;
1471 else if ( !d
->m_paLoadImages
) {
1472 d
->m_paLoadImages
= new KAction( i18n( "Display Images on Page" ), this );
1473 actionCollection()->addAction( "loadImages", d
->m_paLoadImages
);
1474 d
->m_paLoadImages
->setIcon( KIcon( "image-loading" ) );
1475 connect( d
->m_paLoadImages
, SIGNAL( triggered( bool ) ), this, SLOT( slotLoadImages() ) );
1478 if ( d
->m_paLoadImages
) {
1479 QList
<QAction
*> lst
;
1480 lst
.append( d
->m_paLoadImages
);
1481 plugActionList( "loadImages", lst
);
1485 bool KHTMLPart::autoloadImages() const
1488 return d
->m_doc
->docLoader()->autoloadImages();
1493 void KHTMLPart::clear()
1495 if ( d
->m_bCleared
)
1498 d
->m_bCleared
= true;
1500 d
->m_bClearing
= true;
1503 ConstFrameIt it
= d
->m_frames
.constBegin();
1504 const ConstFrameIt end
= d
->m_frames
.constEnd();
1505 for(; it
!= end
; ++it
)
1507 // Stop HTMLRun jobs for frames
1509 (*it
)->m_run
->abort();
1514 ConstFrameIt it
= d
->m_objects
.constBegin();
1515 const ConstFrameIt end
= d
->m_objects
.constEnd();
1516 for(; it
!= end
; ++it
)
1518 // Stop HTMLRun jobs for objects
1520 (*it
)->m_run
->abort();
1525 findTextBegin(); // resets d->m_findNode and d->m_findPos
1526 d
->m_mousePressNode
= DOM::Node();
1531 if (d
->m_doc
->attached()) //the view may have detached it already
1535 // Moving past doc so that onUnload works.
1536 if ( d
->m_frame
&& d
->m_frame
->m_jscript
)
1537 d
->m_frame
->m_jscript
->clear();
1539 // stopping marquees
1540 if (d
->m_doc
&& d
->m_doc
->renderer() && d
->m_doc
->renderer()->layer())
1541 d
->m_doc
->renderer()->layer()->suspendMarquees();
1546 // do not dereference the document before the jscript and view are cleared, as some destructors
1547 // might still try to access the document.
1553 delete d
->m_decoder
;
1556 // We don't want to change between parts if we are going to delete all of them anyway
1557 disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part
* ) ),
1558 this, SLOT( slotActiveFrameChanged( KParts::Part
* ) ) );
1560 if (d
->m_frames
.count())
1562 const KHTMLFrameList frames
= d
->m_frames
;
1563 d
->m_frames
.clear();
1564 ConstFrameIt it
= frames
.begin();
1565 const ConstFrameIt end
= frames
.end();
1566 for(; it
!= end
; ++it
)
1568 if ( (*it
)->m_part
)
1570 partManager()->removePart( (*it
)->m_part
);
1571 delete (KParts::ReadOnlyPart
*)(*it
)->m_part
;
1576 d
->m_suppressedPopupOriginParts
.clear();
1578 if (d
->m_objects
.count())
1580 KHTMLFrameList objects
= d
->m_objects
;
1581 d
->m_objects
.clear();
1582 ConstFrameIt oi
= objects
.constBegin();
1583 const ConstFrameIt oiEnd
= objects
.constEnd();
1585 for (; oi
!= oiEnd
; ++oi
)
1587 if ( (*oi
)->m_part
)
1588 delete (KParts::ReadOnlyPart
*)(*oi
)->m_part
;
1593 // Listen to part changes again
1594 connect( partManager(), SIGNAL( activePartChanged( KParts::Part
* ) ),
1595 this, SLOT( slotActiveFrameChanged( KParts::Part
* ) ) );
1597 d
->clearRedirection();
1598 d
->m_redirectLockHistory
= true;
1599 d
->m_bClearing
= false;
1600 d
->m_frameNameId
= 1;
1601 d
->m_bFirstData
= true;
1603 d
->m_bMousePressed
= false;
1605 if (d
->editor_context
.m_caretBlinkTimer
>= 0)
1606 killTimer(d
->editor_context
.m_caretBlinkTimer
);
1607 d
->editor_context
.reset();
1608 #ifndef QT_NO_CLIPBOARD
1609 connect( qApp
->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
1612 d
->m_jobPercent
= 0;
1614 if ( !d
->m_haveEncoding
)
1615 d
->m_encoding
.clear();
1617 d
->m_DNSPrefetchQueue
.clear();
1618 if (d
->m_DNSPrefetchTimer
> 0)
1619 killTimer(d
->m_DNSPrefetchTimer
);
1620 d
->m_DNSPrefetchTimer
= -1;
1621 d
->m_lookedupHosts
.clear();
1622 if (d
->m_DNSTTLTimer
> 0)
1623 killTimer(d
->m_DNSTTLTimer
);
1624 d
->m_DNSTTLTimer
= -1;
1625 d
->m_numDNSPrefetchedNames
= 0;
1628 d
->m_parsetime
.restart();
1632 bool KHTMLPart::openFile()
1637 DOM::HTMLDocumentImpl
*KHTMLPart::docImpl() const
1639 if ( d
&& d
->m_doc
&& d
->m_doc
->isHTMLDocument() )
1640 return static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
1644 DOM::DocumentImpl
*KHTMLPart::xmlDocImpl() const
1651 void KHTMLPart::slotInfoMessage(KJob
* kio_job
, const QString
& msg
)
1653 assert(d
->m_job
== kio_job
);
1656 setStatusBarText(msg
, BarDefaultText
);
1659 void KHTMLPart::setPageSecurity( PageSecurity sec
)
1661 emit d
->m_extension
->setPageSecurity( sec
);
1664 void KHTMLPart::slotData( KIO::Job
* kio_job
, const QByteArray
&data
)
1666 assert ( d
->m_job
== kio_job
);
1668 //kDebug( 6050 ) << "slotData: " << data.size();
1670 if ( !d
->m_workingURL
.isEmpty() )
1672 //kDebug( 6050 ) << "begin!";
1674 // We must suspend KIO while we're inside begin() because it can cause
1675 // crashes if a window (such as kjsdebugger) goes back into the event loop,
1676 // more data arrives, and begin() gets called again (re-entered).
1677 d
->m_job
->suspend();
1678 begin( d
->m_workingURL
, arguments().xOffset(), arguments().yOffset() );
1681 if (d
->m_cachePolicy
== KIO::CC_Refresh
)
1682 d
->m_doc
->docLoader()->setCachePolicy(KIO::CC_Verify
);
1684 d
->m_doc
->docLoader()->setCachePolicy(d
->m_cachePolicy
);
1686 d
->m_workingURL
= KUrl();
1688 d
->m_cacheId
= KHTMLPageCache::self()->createCacheEntry();
1690 // When the first data arrives, the metadata has just been made available
1691 d
->m_httpHeaders
= d
->m_job
->queryMetaData("HTTP-Headers");
1692 time_t cacheCreationDate
= d
->m_job
->queryMetaData("cache-creation-date").toLong();
1693 d
->m_doc
->docLoader()->setCacheCreationDate(cacheCreationDate
);
1695 d
->m_pageServices
= d
->m_job
->queryMetaData("PageServices");
1696 d
->m_pageReferrer
= d
->m_job
->queryMetaData("referrer");
1697 d
->m_ssl_in_use
= (d
->m_job
->queryMetaData("ssl_in_use") == "TRUE");
1700 KHTMLPart
*p
= parentPart();
1701 if (p
&& p
->d
->m_ssl_in_use
!= d
->m_ssl_in_use
) {
1702 while (p
->parentPart()) p
= p
->parentPart();
1704 p
->setPageSecurity( NotCrypted
);
1708 setPageSecurity( d
->m_ssl_in_use
? Encrypted
: NotCrypted
);
1710 // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
1711 d
->m_ssl_parent_ip
= d
->m_job
->queryMetaData("ssl_parent_ip");
1712 d
->m_ssl_parent_cert
= d
->m_job
->queryMetaData("ssl_parent_cert");
1713 d
->m_ssl_peer_chain
= d
->m_job
->queryMetaData("ssl_peer_chain");
1714 d
->m_ssl_peer_ip
= d
->m_job
->queryMetaData("ssl_peer_ip");
1715 d
->m_ssl_cipher
= d
->m_job
->queryMetaData("ssl_cipher");
1716 d
->m_ssl_protocol_version
= d
->m_job
->queryMetaData("ssl_protocol_version");
1717 d
->m_ssl_cipher_used_bits
= d
->m_job
->queryMetaData("ssl_cipher_used_bits");
1718 d
->m_ssl_cipher_bits
= d
->m_job
->queryMetaData("ssl_cipher_bits");
1719 d
->m_ssl_cert_errors
= d
->m_job
->queryMetaData("ssl_cert_errors");
1721 // Check for charset meta-data
1722 QString qData
= d
->m_job
->queryMetaData("charset");
1723 if ( !qData
.isEmpty() && !d
->m_haveEncoding
) // only use information if the user didn't override the settings
1724 d
->m_encoding
= qData
;
1727 // Support for http-refresh
1728 qData
= d
->m_job
->queryMetaData("http-refresh");
1729 if( !qData
.isEmpty())
1730 d
->m_doc
->processHttpEquiv("refresh", qData
);
1732 // DISABLED: Support Content-Location per section 14.14 of RFC 2616.
1733 // See BR# 51185,BR# 82747
1735 QString baseURL = d->m_job->queryMetaData ("content-location");
1736 if (!baseURL.isEmpty())
1737 d->m_doc->setBaseURL(KUrl( d->m_doc->completeURL(baseURL) ));
1740 // Support for Content-Language
1741 QString language
= d
->m_job
->queryMetaData("content-language");
1742 if (!language
.isEmpty())
1743 d
->m_doc
->setContentLanguage(language
);
1745 if ( !url().isLocalFile() )
1747 // Support for http last-modified
1748 d
->m_lastModified
= d
->m_job
->queryMetaData("modified");
1751 d
->m_lastModified
.clear(); // done on-demand by lastModified()
1754 KHTMLPageCache::self()->addData(d
->m_cacheId
, data
);
1755 write( data
.data(), data
.size() );
1757 if (d
->m_frame
&& d
->m_frame
->m_jscript
)
1758 d
->m_frame
->m_jscript
->dataReceived();
1762 void KHTMLPart::slotRestoreData(const QByteArray
&data
)
1765 if ( !d
->m_workingURL
.isEmpty() )
1767 long saveCacheId
= d
->m_cacheId
;
1768 QString savePageReferrer
= d
->m_pageReferrer
;
1769 QString saveEncoding
= d
->m_encoding
;
1770 begin( d
->m_workingURL
, arguments().xOffset(), arguments().yOffset() );
1771 d
->m_encoding
= saveEncoding
;
1772 d
->m_pageReferrer
= savePageReferrer
;
1773 d
->m_cacheId
= saveCacheId
;
1774 d
->m_workingURL
= KUrl();
1777 //kDebug( 6050 ) << data.size();
1778 write( data
.data(), data
.size() );
1780 if (data
.size() == 0)
1782 //kDebug( 6050 ) << "<<end of data>>";
1784 if (d
->m_doc
&& d
->m_doc
->parsing())
1785 end(); //will emit completed()
1789 void KHTMLPart::showError( KJob
* job
)
1791 kDebug(6050) << "d->m_bParsing=" << (d
->m_doc
&& d
->m_doc
->parsing()) << " d->m_bComplete=" << d
->m_bComplete
1792 << " d->m_bCleared=" << d
->m_bCleared
;
1794 if (job
->error() == KIO::ERR_NO_CONTENT
)
1797 if ( (d
->m_doc
&& d
->m_doc
->parsing()) || d
->m_workingURL
.isEmpty() ) // if we got any data already
1798 job
->uiDelegate()->showErrorMessage();
1801 htmlError( job
->error(), job
->errorText(), d
->m_workingURL
);
1805 // This is a protected method, placed here because of it's relevance to showError
1806 void KHTMLPart::htmlError( int errorCode
, const QString
& text
, const KUrl
& reqUrl
)
1808 kDebug(6050) << "errorCode" << errorCode
<< "text" << text
;
1809 // make sure we're not executing any embedded JS
1810 bool bJSFO
= d
->m_bJScriptForce
;
1811 bool bJSOO
= d
->m_bJScriptOverride
;
1812 d
->m_bJScriptForce
= false;
1813 d
->m_bJScriptOverride
= true;
1816 QString errorName
, techName
, description
;
1817 QStringList causes
, solutions
;
1819 QByteArray raw
= KIO::rawErrorDetail( errorCode
, text
, &reqUrl
);
1820 QDataStream
stream(raw
);
1822 stream
>> errorName
>> techName
>> description
>> causes
>> solutions
;
1824 QString url
, protocol
, datetime
;
1825 url
= Qt::escape( reqUrl
.prettyUrl() );
1826 protocol
= reqUrl
.protocol();
1827 datetime
= KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
1828 KLocale::LongDate
);
1830 QString
filename( KStandardDirs::locate( "data", "khtml/error.html" ) );
1831 QFile
file( filename
);
1832 bool isOpened
= file
.open( QIODevice::ReadOnly
);
1834 kWarning(6050) << "Could not open error html template:" << filename
;
1836 QString html
= QString( QLatin1String( file
.readAll() ) );
1838 html
.replace( QLatin1String( "TITLE" ), i18n( "Error: %1 - %2", errorName
, url
) );
1839 html
.replace( QLatin1String( "DIRECTION" ), QApplication::isRightToLeft() ? "rtl" : "ltr" );
1840 html
.replace( QLatin1String( "ICON_PATH" ), KIconLoader::global()->iconPath( "dialog-warning", -KIconLoader::SizeHuge
) );
1842 QString doc
= QLatin1String( "<h1>" );
1843 doc
+= i18n( "The requested operation could not be completed" );
1844 doc
+= QLatin1String( "</h1><h2>" );
1846 doc
+= QLatin1String( "</h2>" );
1847 if ( !techName
.isNull() ) {
1848 doc
+= QLatin1String( "<h2>" );
1849 doc
+= i18n( "Technical Reason: " );
1851 doc
+= QLatin1String( "</h2>" );
1853 doc
+= QLatin1String( "<h3>" );
1854 doc
+= i18n( "Details of the Request:" );
1855 doc
+= QLatin1String( "</h3><ul><li>" );
1856 doc
+= i18n( "URL: %1" , url
);
1857 doc
+= QLatin1String( "</li><li>" );
1858 if ( !protocol
.isNull() ) {
1859 doc
+= i18n( "Protocol: %1", protocol
);
1860 doc
+= QLatin1String( "</li><li>" );
1862 doc
+= i18n( "Date and Time: %1" , datetime
);
1863 doc
+= QLatin1String( "</li><li>" );
1864 doc
+= i18n( "Additional Information: %1" , text
);
1865 doc
+= QLatin1String( "</li></ul><h3>" );
1866 doc
+= i18n( "Description:" );
1867 doc
+= QLatin1String( "</h3><p>" );
1869 doc
+= QLatin1String( "</p>" );
1870 if ( causes
.count() ) {
1871 doc
+= QLatin1String( "<h3>" );
1872 doc
+= i18n( "Possible Causes:" );
1873 doc
+= QLatin1String( "</h3><ul><li>" );
1874 doc
+= causes
.join( "</li><li>" );
1875 doc
+= QLatin1String( "</li></ul>" );
1877 if ( solutions
.count() ) {
1878 doc
+= QLatin1String( "<h3>" );
1879 doc
+= i18n( "Possible Solutions:" );
1880 doc
+= QLatin1String( "</h3><ul><li>" );
1881 doc
+= solutions
.join( "</li><li>" );
1882 doc
+= QLatin1String( "</li></ul>" );
1885 html
.replace( QLatin1String("TEXT"), doc
);
1890 d
->m_bJScriptForce
= bJSFO
;
1891 d
->m_bJScriptOverride
= bJSOO
;
1893 // make the working url the current url, so that reload works and
1894 // emit the progress signals to advance one step in the history
1895 // (so that 'back' works)
1896 setUrl(reqUrl
); // same as d->m_workingURL
1897 d
->m_workingURL
= KUrl();
1902 void KHTMLPart::slotFinished( KJob
* job
)
1909 KHTMLPageCache::self()->cancelEntry(d
->m_cacheId
);
1911 // The following catches errors that occur as a result of HTTP
1912 // to FTP redirections where the FTP URL is a directory. Since
1913 // KIO cannot change a redirection request from GET to LISTDIR,
1914 // we have to take care of it here once we know for sure it is
1916 if (job
->error() == KIO::ERR_IS_DIRECTORY
)
1918 emit
canceled( job
->errorString() );
1919 emit d
->m_extension
->openUrlRequest( d
->m_workingURL
);
1923 emit
canceled( job
->errorString() );
1924 // TODO: what else ?
1931 KIO::TransferJob
*tjob
= ::qobject_cast
<KIO::TransferJob
*>(job
);
1932 if (tjob
&& tjob
->isErrorPage()) {
1933 HTMLPartContainerElementImpl
*elt
= d
->m_frame
?
1934 (HTMLPartContainerElementImpl
*)d
->m_frame
->m_partContainerElement
: 0;
1939 elt
->partLoadingErrorNotify();
1941 if (d
->m_bComplete
) return;
1944 //kDebug( 6050 ) << "slotFinished";
1946 KHTMLPageCache::self()->endData(d
->m_cacheId
);
1947 if (d
->m_frame
&& d
->m_frame
->m_jscript
)
1948 d
->m_frame
->m_jscript
->dataReceived();
1950 if ( d
->m_doc
&& d
->m_doc
->docLoader()->expireDate() && url().protocol().toLower().startsWith("http"))
1951 KIO::http_update_cache(url(), false, d
->m_doc
->docLoader()->expireDate());
1953 d
->m_workingURL
= KUrl();
1955 if ( d
->m_doc
&& d
->m_doc
->parsing())
1956 end(); //will emit completed()
1959 void KHTMLPart::begin( const KUrl
&url
, int xOffset
, int yOffset
)
1961 // No need to show this for a new page until an error is triggered
1962 if (!parentPart()) {
1963 removeJSErrorExtension();
1964 setSuppressedPopupIndicator( false );
1965 d
->m_openableSuppressedPopups
= 0;
1966 foreach ( KHTMLPart
* part
, d
->m_suppressedPopupOriginParts
) {
1968 KJS::Window
*w
= KJS::Window::retrieveWindow( part
);
1970 w
->forgetSuppressedWindows();
1975 d
->m_bCleared
= false;
1977 d
->m_bComplete
= false;
1978 d
->m_bLoadEventEmitted
= false;
1980 d
->m_bCleared
= false;
1983 QString urlString
= url
.url();
1984 KHTMLGlobal::vLinks()->insert( urlString
);
1985 QString urlString2
= url
.prettyUrl();
1986 if ( urlString
!= urlString2
) {
1987 KHTMLGlobal::vLinks()->insert( urlString2
);
1994 KParts::OpenUrlArguments args
= arguments();
1995 args
.setXOffset(xOffset
);
1996 args
.setYOffset(yOffset
);
1999 d
->m_pageReferrer
.clear();
2002 d
->m_referrer
= ref
.protocol().startsWith("http") ? ref
.url() : "";
2006 bool servedAsXHTML
= args
.mimeType() == "application/xhtml+xml";
2007 bool servedAsSVG
= !servedAsXHTML
&& args
.mimeType() == "image/svg+xml";
2008 KMimeType::Ptr mime
= KMimeType::mimeType( args
.mimeType(), KMimeType::ResolveAliases
);
2009 // We want to make sure text/xml and application/xml are both handled right...
2010 bool servedAsXML
= mime
&& mime
->is( "text/xml" );
2011 // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
2012 if ( servedAsSVG
) {
2013 d
->m_doc
= DOMImplementationImpl::instance()->createSVGDocument( d
->m_view
);
2015 if ( servedAsXML
&& !servedAsXHTML
) { // any XML derivative, except XHTML
2016 d
->m_doc
= DOMImplementationImpl::instance()->createXMLDocument( d
->m_view
);
2018 d
->m_doc
= DOMImplementationImpl::instance()->createHTMLDocument( d
->m_view
);
2019 // HTML or XHTML? (#86446)
2020 static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->setHTMLRequested( !servedAsXHTML
);
2025 d
->m_doc
->setURL( url
.url() );
2027 if (!d
->m_doc
->attached())
2028 d
->m_doc
->attach( );
2029 d
->m_doc
->setBaseURL( KUrl() );
2030 d
->m_doc
->docLoader()->setShowAnimations( KHTMLGlobal::defaultHTMLSettings()->showAnimations() );
2033 d
->m_paUseStylesheet
->setItems(QStringList());
2034 d
->m_paUseStylesheet
->setEnabled( false );
2036 setAutoloadImages( KHTMLGlobal::defaultHTMLSettings()->autoLoadImages() );
2037 QString userStyleSheet
= KHTMLGlobal::defaultHTMLSettings()->userStyleSheet();
2038 if ( !userStyleSheet
.isEmpty() )
2039 setUserStyleSheet( KUrl( userStyleSheet
) );
2041 d
->m_doc
->setRestoreState(d
->m_extension
->browserArguments().docState
);
2042 connect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2044 emit d
->m_extension
->enableAction( "print", true );
2046 d
->m_doc
->setParsing(true);
2049 void KHTMLPart::write( const char *data
, int len
)
2051 if ( !d
->m_decoder
)
2052 d
->m_decoder
= createDecoder();
2055 len
= strlen( data
);
2060 QString decoded
=d
->m_decoder
->decodeWithBuffering(data
,len
);
2062 if(decoded
.isEmpty())
2068 khtml::Tokenizer
* t
= d
->m_doc
->tokenizer();
2070 t
->write( decoded
, true );
2074 void KHTMLPart::setAlwaysHonourDoctype( bool b
)
2076 d
->m_bStrictModeQuirk
= !b
;
2079 void KHTMLPart::write( const QString
&str
)
2084 if(d
->m_bFirstData
) {
2085 // determine the parse mode
2086 if (d
->m_bStrictModeQuirk
) {
2087 d
->m_doc
->setParseMode( DocumentImpl::Strict
);
2088 d
->m_bFirstData
= false;
2093 khtml::Tokenizer
* t
= d
->m_doc
->tokenizer();
2095 t
->write( str
, true );
2098 void KHTMLPart::end()
2103 QString decoded
=d
->m_decoder
->flush();
2104 if (d
->m_bFirstData
)
2106 if (!decoded
.isEmpty())
2109 d
->m_doc
->finishParsing();
2113 void KHTMLPart::onFirstData()
2115 assert( d
->m_bFirstData
);
2117 // determine the parse mode
2118 d
->m_doc
->determineParseMode();
2119 d
->m_bFirstData
= false;
2121 // ### this is still quite hacky, but should work a lot better than the old solution
2122 if (d
->m_decoder
->visuallyOrdered())
2123 d
->m_doc
->setVisuallyOrdered();
2124 d
->m_doc
->recalcStyle( NodeImpl::Force
);
2127 bool KHTMLPart::doOpenStream( const QString
& mimeType
)
2129 KMimeType::Ptr mime
= KMimeType::mimeType(mimeType
, KMimeType::ResolveAliases
);
2130 if ( mime
&& ( mime
->is( "text/html" ) || mime
->is( "text/xml" ) ) )
2138 bool KHTMLPart::doWriteStream( const QByteArray
& data
)
2140 write( data
.data(), data
.size() );
2144 bool KHTMLPart::doCloseStream()
2151 void KHTMLPart::paint(QPainter
*p
, const QRect
&rc
, int yOff
, bool *more
)
2153 if (!d
->m_view
) return;
2154 d
->m_view
->paint(p
, rc
, yOff
, more
);
2157 void KHTMLPart::stopAnimations()
2160 d
->m_doc
->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled
);
2162 ConstFrameIt it
= d
->m_frames
.constBegin();
2163 const ConstFrameIt end
= d
->m_frames
.constEnd();
2164 for (; it
!= end
; ++it
)
2165 if ( !(*it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
2166 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
2167 static_cast<KHTMLPart
*>( p
)->stopAnimations();
2171 void KHTMLPart::resetFromScript()
2174 d
->m_bComplete
= false;
2175 d
->m_bLoadEventEmitted
= false;
2176 disconnect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2177 connect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2178 d
->m_doc
->setParsing(true);
2183 void KHTMLPart::slotFinishedParsing()
2185 d
->m_doc
->setParsing(false);
2186 d
->m_doc
->dispatchWindowEvent(EventImpl::KHTML_CONTENTLOADED_EVENT
, false, false);
2187 checkEmitLoadEvent();
2188 disconnect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2191 return; // We are probably being destructed.
2196 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader
* dl
, khtml::CachedObject
*obj
)
2198 if ( obj
&& obj
->type() == khtml::CachedObject::Image
&& d
->m_doc
&& d
->m_doc
->docLoader() == dl
) {
2199 KHTMLPart
* p
= this;
2201 KHTMLPart
* const op
= p
;
2202 ++(p
->d
->m_totalObjectCount
);
2203 p
= p
->parentPart();
2204 if ( !p
&& op
->d
->m_loadedObjects
<= op
->d
->m_totalObjectCount
2205 && !op
->d
->m_progressUpdateTimer
.isActive()) {
2206 op
->d
->m_progressUpdateTimer
.setSingleShot( true );
2207 op
->d
->m_progressUpdateTimer
.start( 200 );
2213 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader
* dl
, khtml::CachedObject
*obj
)
2215 if ( obj
&& obj
->type() == khtml::CachedObject::Image
&& d
->m_doc
&& d
->m_doc
->docLoader() == dl
) {
2216 KHTMLPart
* p
= this;
2218 KHTMLPart
* const op
= p
;
2219 ++(p
->d
->m_loadedObjects
);
2220 p
= p
->parentPart();
2221 if ( !p
&& op
->d
->m_loadedObjects
<= op
->d
->m_totalObjectCount
&& op
->d
->m_jobPercent
<= 100
2222 && !op
->d
->m_progressUpdateTimer
.isActive()) {
2223 op
->d
->m_progressUpdateTimer
.setSingleShot( true );
2224 op
->d
->m_progressUpdateTimer
.start( 200 );
2232 void KHTMLPart::slotProgressUpdate()
2235 if ( d
->m_loadedObjects
< d
->m_totalObjectCount
)
2236 percent
= d
->m_jobPercent
/ 4 + ( d
->m_loadedObjects
*300 ) / ( 4*d
->m_totalObjectCount
);
2238 percent
= d
->m_jobPercent
;
2240 if( d
->m_bComplete
)
2243 if (d
->m_statusMessagesEnabled
) {
2244 if( d
->m_bComplete
)
2245 emit d
->m_extension
->infoMessage( i18n( "Page loaded." ));
2246 else if ( d
->m_loadedObjects
< d
->m_totalObjectCount
&& percent
>= 75 )
2247 emit d
->m_extension
->infoMessage( i18np( "%1 Image of %2 loaded.", "%1 Images of %2 loaded.", d
->m_loadedObjects
, d
->m_totalObjectCount
) );
2250 emit d
->m_extension
->loadingProgress( percent
);
2253 void KHTMLPart::slotJobSpeed( KJob
* /*job*/, unsigned long speed
)
2255 d
->m_jobspeed
= speed
;
2257 setStatusBarText(jsStatusBarText(), BarOverrideText
);
2260 void KHTMLPart::slotJobPercent( KJob
* /*job*/, unsigned long percent
)
2262 d
->m_jobPercent
= percent
;
2264 if ( !parentPart() ) {
2265 d
->m_progressUpdateTimer
.setSingleShot( true );
2266 d
->m_progressUpdateTimer
.start( 0 );
2270 void KHTMLPart::slotJobDone( KJob
* /*job*/ )
2272 d
->m_jobPercent
= 100;
2274 if ( !parentPart() ) {
2275 d
->m_progressUpdateTimer
.setSingleShot( true );
2276 d
->m_progressUpdateTimer
.start( 0 );
2280 void KHTMLPart::slotUserSheetStatDone( KJob
*_job
)
2282 using namespace KIO
;
2284 if ( _job
->error() ) {
2289 const UDSEntry entry
= dynamic_cast<KIO::StatJob
*>( _job
)->statResult();
2290 const time_t lastModified
= entry
.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME
, -1 );
2292 // If the filesystem supports modification times, only reload the
2293 // user-defined stylesheet if necessary - otherwise always reload.
2294 if ( lastModified
!= static_cast<time_t>(-1) ) {
2295 if ( d
->m_userStyleSheetLastModified
>= lastModified
) {
2298 d
->m_userStyleSheetLastModified
= lastModified
;
2301 setUserStyleSheet( KUrl( settings()->userStyleSheet() ) );
2304 void KHTMLPart::checkCompleted()
2306 // kDebug( 6050 ) << this << name();
2307 // kDebug( 6050 ) << " parsing: " << (d->m_doc && d->m_doc->parsing());
2308 // kDebug( 6050 ) << " complete: " << d->m_bComplete;
2310 // restore the cursor position
2311 if (d
->m_doc
&& !d
->m_doc
->parsing() && !d
->m_focusNodeRestored
)
2313 if (d
->m_focusNodeNumber
>= 0)
2314 d
->m_doc
->setFocusNode(d
->m_doc
->nodeWithAbsIndex(d
->m_focusNodeNumber
));
2316 d
->m_focusNodeRestored
= true;
2319 bool bPendingChildRedirection
= false;
2320 // Any frame that hasn't completed yet ?
2321 ConstFrameIt it
= d
->m_frames
.constBegin();
2322 const ConstFrameIt end
= d
->m_frames
.constEnd();
2323 for (; it
!= end
; ++it
) {
2324 if ( !(*it
)->m_bCompleted
)
2326 //kDebug( 6050 ) << this << " is waiting for " << (*it)->m_part;
2329 // Check for frames with pending redirections
2330 if ( (*it
)->m_bPendingRedirection
)
2331 bPendingChildRedirection
= true;
2334 // Any object that hasn't completed yet ?
2336 ConstFrameIt oi
= d
->m_objects
.constBegin();
2337 const ConstFrameIt oiEnd
= d
->m_objects
.constEnd();
2339 for (; oi
!= oiEnd
; ++oi
)
2340 if ( !(*oi
)->m_bCompleted
)
2343 // Are we still parsing - or have we done the completed stuff already ?
2344 if ( d
->m_bComplete
|| (d
->m_doc
&& d
->m_doc
->parsing()) )
2347 // Still waiting for images/scripts from the loader ?
2349 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
2350 requests
= khtml::Cache::loader()->numRequests( d
->m_doc
->docLoader() );
2354 //kDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests;
2359 // Now do what should be done when we are really completed.
2360 d
->m_bComplete
= true;
2361 d
->m_cachePolicy
= KProtocolManager::cacheControl(); // reset cache policy
2362 d
->m_totalObjectCount
= 0;
2363 d
->m_loadedObjects
= 0;
2365 KHTMLPart
* p
= this;
2368 p
= p
->parentPart();
2369 if ( !p
&& !op
->d
->m_progressUpdateTimer
.isActive()) {
2370 op
->d
->m_progressUpdateTimer
.setSingleShot( true );
2371 op
->d
->m_progressUpdateTimer
.start( 0 );
2375 checkEmitLoadEvent(); // if we didn't do it before
2377 bool pendingAction
= false;
2379 if ( !d
->m_redirectURL
.isEmpty() )
2381 // DA: Do not start redirection for frames here! That action is
2382 // deferred until the parent emits a completed signal.
2383 if ( parentPart() == 0 ) {
2384 //kDebug(6050) << this << " starting redirection timer";
2385 d
->m_redirectionTimer
.setSingleShot( true );
2386 d
->m_redirectionTimer
.start( qMax(0, 1000 * d
->m_delayRedirect
) );
2388 //kDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted.";
2391 pendingAction
= true;
2393 else if ( bPendingChildRedirection
)
2395 pendingAction
= true;
2398 // the view will emit completed on our behalf,
2399 // either now or at next repaint if one is pending
2401 //kDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction;
2402 d
->m_view
->complete( pendingAction
);
2404 // find the alternate stylesheets
2407 sheets
= d
->m_doc
->availableStyleSheets();
2408 sheets
.prepend( i18n( "Automatic Detection" ) );
2409 d
->m_paUseStylesheet
->setItems( sheets
);
2411 d
->m_paUseStylesheet
->setEnabled( sheets
.count() > 2);
2412 if (sheets
.count() > 2)
2414 d
->m_paUseStylesheet
->setCurrentItem(qMax(sheets
.indexOf(d
->m_sheetUsed
), 0));
2415 slotUseStylesheet();
2418 setJSDefaultStatusBarText(QString());
2421 kDebug(6050) << "DONE: " <<d
->m_parsetime
.elapsed();
2425 void KHTMLPart::checkEmitLoadEvent()
2427 if ( d
->m_bLoadEventEmitted
|| !d
->m_doc
|| d
->m_doc
->parsing() ) return;
2429 ConstFrameIt it
= d
->m_frames
.constBegin();
2430 const ConstFrameIt end
= d
->m_frames
.constEnd();
2431 for (; it
!= end
; ++it
)
2432 if ( !(*it
)->m_bCompleted
) // still got a frame running -> too early
2435 ConstFrameIt oi
= d
->m_objects
.constBegin();
2436 const ConstFrameIt oiEnd
= d
->m_objects
.constEnd();
2438 for (; oi
!= oiEnd
; ++oi
)
2439 if ( !(*oi
)->m_bCompleted
) // still got a object running -> too early
2442 // Still waiting for images/scripts from the loader ?
2443 // (onload must happen afterwards, #45607)
2444 // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
2446 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
2447 requests
= khtml::Cache::loader()->numRequests( d
->m_doc
->docLoader() );
2452 d
->m_bLoadEventEmitted
= true;
2457 const KHTMLSettings
*KHTMLPart::settings() const
2459 return d
->m_settings
;
2462 #ifndef KDE_NO_COMPAT
2463 KUrl
KHTMLPart::baseURL() const
2465 if ( !d
->m_doc
) return KUrl();
2467 return d
->m_doc
->baseURL();
2471 KUrl
KHTMLPart::completeURL( const QString
&url
)
2473 if ( !d
->m_doc
) return KUrl( url
);
2477 return KUrl(d
->m_doc
->completeURL(url
), d
->m_decoder
->codec()->mibEnum());
2480 return KUrl( d
->m_doc
->completeURL( url
) );
2483 QString
KHTMLPartPrivate::codeForJavaScriptURL(const QString
&u
)
2485 return KUrl::fromPercentEncoding( u
.right( u
.length() - 11 ).toUtf8() );
2488 void KHTMLPartPrivate::executeJavascriptURL(const QString
&u
)
2490 QString script
= codeForJavaScriptURL(u
);
2491 kDebug( 6050 ) << "script=" << script
;
2492 QVariant res
= q
->executeScript( DOM::Node(), script
);
2493 if ( res
.type() == QVariant::String
) {
2494 q
->begin( q
->url() );
2495 q
->write( res
.toString() );
2498 emit q
->completed();
2501 bool KHTMLPartPrivate::isJavaScriptURL(const QString
& url
)
2503 return url
.indexOf( QLatin1String( "javascript:" ), 0, Qt::CaseInsensitive
) == 0;
2506 // Called by ecma/kjs_window in case of redirections from Javascript,
2507 // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
2508 void KHTMLPart::scheduleRedirection( int delay
, const QString
&url
, bool doLockHistory
)
2510 kDebug(6050) << "delay=" << delay
<< " url=" << url
;
2511 kDebug(6050) << "current redirectURL=" << d
->m_redirectURL
<< " with delay " << d
->m_delayRedirect
;
2513 // In case of JS redirections, some, such as jump to anchors, and javascript:
2514 // evaluation should actually be handled immediately, and not waiting until
2515 // the end of the script. (Besides, we don't want to abort the tokenizer for those)
2516 if ( delay
== -1 && d
->isInPageURL(url
) ) {
2517 d
->executeInPageURL(url
, doLockHistory
);
2521 if( delay
< 24*60*60 &&
2522 ( d
->m_redirectURL
.isEmpty() || delay
<= d
->m_delayRedirect
) ) {
2523 d
->m_delayRedirect
= delay
;
2524 d
->m_redirectURL
= url
;
2525 d
->m_redirectLockHistory
= doLockHistory
;
2526 kDebug(6050) << " d->m_bComplete=" << d
->m_bComplete
;
2528 if ( d
->m_bComplete
) {
2529 d
->m_redirectionTimer
.stop();
2530 d
->m_redirectionTimer
.setSingleShot( true );
2531 d
->m_redirectionTimer
.start( qMax(0, 1000 * d
->m_delayRedirect
) );
2536 void KHTMLPartPrivate::clearRedirection()
2538 m_delayRedirect
= 0;
2539 m_redirectURL
.clear();
2540 m_redirectionTimer
.stop();
2543 void KHTMLPart::slotRedirect()
2545 kDebug(6050) << this;
2546 QString u
= d
->m_redirectURL
;
2548 d
->clearRedirection();
2550 if ( d
->isInPageURL(u
) )
2552 d
->executeInPageURL(u
, d
->m_redirectLockHistory
);
2556 KParts::OpenUrlArguments args
;
2557 KUrl
cUrl( this->url() );
2559 // handle windows opened by JS
2560 if ( openedByJS() && d
->m_opener
)
2561 cUrl
= d
->m_opener
->url();
2563 if (!KAuthorized::authorizeUrlAction("redirect", cUrl
, url
))
2565 kWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl
<< " to " << url
<< " REJECTED!";
2570 if ( urlcmp( u
, this->url().url(), KUrl::CompareWithoutTrailingSlash
| KUrl::CompareWithoutFragment
) )
2572 args
.metaData().insert("referrer", d
->m_pageReferrer
);
2575 // For javascript and META-tag based redirections:
2576 // - We don't take cross-domain-ness in consideration if we are the
2577 // toplevel frame because the new URL may be in a different domain as the current URL
2579 // - If we are not the toplevel frame then we check against the toplevelURL()
2581 args
.metaData().insert("cross-domain", toplevelURL().url());
2583 KParts::BrowserArguments browserArgs
;
2584 browserArgs
.setLockHistory( d
->m_redirectLockHistory
);
2585 // _self: make sure we don't use any <base target=>'s
2587 if ( !urlSelected( u
, 0, 0, "_self", args
, browserArgs
) ) {
2588 // urlSelected didn't open a url, so emit completed ourselves
2593 void KHTMLPart::slotRedirection(KIO::Job
*, const KUrl
& url
)
2595 // the slave told us that we got redirected
2596 //kDebug( 6050 ) << "redirection by KIO to" << url;
2597 emit d
->m_extension
->setLocationBarUrl( url
.prettyUrl() );
2598 d
->m_workingURL
= url
;
2601 bool KHTMLPart::setEncoding( const QString
&name
, bool override
)
2603 d
->m_encoding
= name
;
2604 d
->m_haveEncoding
= override
;
2606 if( !url().isEmpty() ) {
2609 KUrl oldUrl
= url();
2611 d
->m_restored
= true;
2613 d
->m_restored
= false;
2619 QString
KHTMLPart::encoding() const
2621 if(d
->m_haveEncoding
&& !d
->m_encoding
.isEmpty())
2622 return d
->m_encoding
;
2624 if(d
->m_decoder
&& d
->m_decoder
->encoding())
2625 return QString(d
->m_decoder
->encoding());
2627 return defaultEncoding();
2630 QString
KHTMLPart::defaultEncoding() const
2632 QString encoding
= settings()->encoding();
2633 if ( !encoding
.isEmpty() )
2635 // HTTP requires the default encoding to be latin1, when neither
2636 // the user nor the page requested a particular encoding.
2637 if ( url().protocol().startsWith( "http" ) )
2638 return "iso-8859-1";
2640 return KGlobal::locale()->encoding();
2643 void KHTMLPart::setUserStyleSheet(const KUrl
&url
)
2645 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
2646 (void) new khtml::PartStyleSheetLoader(this, url
.url(), d
->m_doc
->docLoader());
2649 void KHTMLPart::setUserStyleSheet(const QString
&styleSheet
)
2652 d
->m_doc
->setUserStyleSheet( styleSheet
);
2655 bool KHTMLPart::gotoAnchor( const QString
&name
)
2660 HTMLCollectionImpl
*anchors
=
2661 new HTMLCollectionImpl( d
->m_doc
, HTMLCollectionImpl::DOC_ANCHORS
);
2663 NodeImpl
*n
= anchors
->namedItem(name
);
2667 n
= d
->m_doc
->getElementById( name
);
2670 d
->m_doc
->setCSSTarget(n
); // Setting to null will clear the current target.
2672 // Implement the rule that "" and "top" both mean top of page as in other browsers.
2673 bool quirkyName
= !n
&& !d
->m_doc
->inStrictMode() && (name
.isEmpty() || name
.toLower() == "top");
2676 d
->m_view
->setContentsPos( d
->m_view
->contentsX(), 0);
2679 kDebug(6050) << name
<< "not found";
2685 HTMLElementImpl
*a
= static_cast<HTMLElementImpl
*>(n
);
2687 a
->getUpperLeftCorner(x
, y
);
2688 if (x
<= d
->m_view
->contentsX())
2691 gox
= d
->m_view
->contentsX();
2692 if ( x
+ 10 > d
->m_view
->contentsX()+d
->m_view
->visibleWidth()) {
2693 a
->getLowerRightCorner(x
, dummy
);
2694 gox
= x
- d
->m_view
->visibleWidth() + 10;
2698 d
->m_view
->setContentsPos(gox
, y
);
2703 bool KHTMLPart::nextAnchor()
2707 d
->m_view
->focusNextPrevNode ( true );
2712 bool KHTMLPart::prevAnchor()
2716 d
->m_view
->focusNextPrevNode ( false );
2721 void KHTMLPart::setStandardFont( const QString
&name
)
2723 d
->m_settings
->setStdFontName(name
);
2726 void KHTMLPart::setFixedFont( const QString
&name
)
2728 d
->m_settings
->setFixedFontName(name
);
2731 void KHTMLPart::setURLCursor( const QCursor
&c
)
2733 d
->m_linkCursor
= c
;
2736 QCursor
KHTMLPart::urlCursor() const
2738 return d
->m_linkCursor
;
2741 bool KHTMLPart::onlyLocalReferences() const
2743 return d
->m_onlyLocalReferences
;
2746 void KHTMLPart::setOnlyLocalReferences(bool enable
)
2748 d
->m_onlyLocalReferences
= enable
;
2751 void KHTMLPartPrivate::setFlagRecursively(
2752 bool KHTMLPartPrivate::*flag
, bool value
)
2754 // first set it on the current one
2755 this->*flag
= value
;
2757 // descend into child frames recursively
2759 QList
<khtml::ChildFrame
*>::Iterator it
= m_frames
.begin();
2760 const QList
<khtml::ChildFrame
*>::Iterator itEnd
= m_frames
.end();
2761 for (; it
!= itEnd
; ++it
) {
2762 KHTMLPart
* const part
= qobject_cast
<KHTMLPart
*>( (*it
)->m_part
);
2764 part
->d
->setFlagRecursively(flag
, value
);
2767 // do the same again for objects
2769 QList
<khtml::ChildFrame
*>::Iterator it
= m_objects
.begin();
2770 const QList
<khtml::ChildFrame
*>::Iterator itEnd
= m_objects
.end();
2771 for (; it
!= itEnd
; ++it
) {
2772 KHTMLPart
* const part
= qobject_cast
<KHTMLPart
*>( (*it
)->m_part
);
2774 part
->d
->setFlagRecursively(flag
, value
);
2779 void KHTMLPart::initCaret()
2781 // initialize caret if not used yet
2782 if (d
->editor_context
.m_selection
.state() == Selection::NONE
) {
2785 if (d
->m_doc
->isHTMLDocument()) {
2786 HTMLDocumentImpl
* htmlDoc
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
2787 node
= htmlDoc
->body();
2791 d
->editor_context
.m_selection
.moveTo(Position(node
, 0));
2792 d
->editor_context
.m_selection
.setNeedsLayout();
2793 d
->editor_context
.m_selection
.needsCaretRepaint();
2798 static void setCaretInvisibleIfNeeded(KHTMLPart
*part
)
2800 // On contenteditable nodes, don't hide the caret
2801 if (!khtml::KHTMLPartAccessor::caret(part
).caretPos().node()->isContentEditable())
2802 part
->setCaretVisible(false);
2805 void KHTMLPart::setCaretMode(bool enable
)
2807 kDebug(6200) << enable
;
2808 if (isCaretMode() == enable
) return;
2809 d
->setFlagRecursively(&KHTMLPartPrivate::m_caretMode
, enable
);
2810 // FIXME: this won't work on frames as expected
2811 if (!isEditable()) {
2814 setCaretVisible(true);
2815 // view()->ensureCaretVisible();
2817 setCaretInvisibleIfNeeded(this);
2822 bool KHTMLPart::isCaretMode() const
2824 return d
->m_caretMode
;
2827 void KHTMLPart::setEditable(bool enable
)
2829 if (isEditable() == enable
) return;
2830 d
->setFlagRecursively(&KHTMLPartPrivate::m_designMode
, enable
);
2831 // FIXME: this won't work on frames as expected
2832 if (!isCaretMode()) {
2835 setCaretVisible(true);
2836 // view()->ensureCaretVisible();
2838 setCaretInvisibleIfNeeded(this);
2842 bool KHTMLPart::isEditable() const
2844 return d
->m_designMode
;
2847 khtml::EditorContext
*KHTMLPart::editorContext() const {
2848 return &d
->editor_context
;
2851 void KHTMLPart::setCaretPosition(DOM::Node node
, long offset
, bool extendSelection
)
2853 #ifndef KHTML_NO_CARET
2855 kDebug(6200) << "node: " << node
.handle() << " nodeName: "
2856 << node
.nodeName().string() << " offset: " << offset
2857 << " extendSelection " << extendSelection
;
2858 if (view()->moveCaretTo(node
.handle(), offset
, !extendSelection
))
2859 emitSelectionChanged();
2860 view()->ensureCaretVisible();
2862 #endif // KHTML_NO_CARET
2865 KHTMLPart::CaretDisplayPolicy
KHTMLPart::caretDisplayPolicyNonFocused() const
2868 #ifndef KHTML_NO_CARET
2869 return (CaretDisplayPolicy
)view()->caretDisplayPolicyNonFocused();
2870 #else // KHTML_NO_CARET
2871 return CaretInvisible
;
2872 #endif // KHTML_NO_CARET
2874 return CaretInvisible
;
2877 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy
)
2880 #ifndef KHTML_NO_CARET
2881 view()->setCaretDisplayPolicyNonFocused(policy
);
2882 #endif // KHTML_NO_CARET
2886 void KHTMLPart::setCaretVisible(bool show
)
2889 NodeImpl
*caretNode
= d
->editor_context
.m_selection
.caretPos().node();
2890 if (isCaretMode() || (caretNode
&& caretNode
->isContentEditable())) {
2891 invalidateSelection();
2892 enableFindAheadActions(false);
2896 if (d
->editor_context
.m_caretBlinkTimer
>= 0)
2897 killTimer(d
->editor_context
.m_caretBlinkTimer
);
2898 clearCaretRectIfNeeded();
2903 void KHTMLPart::findTextBegin()
2905 d
->m_find
.findTextBegin();
2908 bool KHTMLPart::initFindNode( bool selection
, bool reverse
, bool fromCursor
)
2910 return d
->m_find
.initFindNode(selection
, reverse
, fromCursor
);
2913 void KHTMLPart::slotFind()
2915 KParts::ReadOnlyPart
*part
= currentFrame();
2918 if (!part
->inherits("KHTMLPart") )
2920 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2923 static_cast<KHTMLPart
*>( part
)->findText();
2926 void KHTMLPart::slotFindNext()
2928 KParts::ReadOnlyPart
*part
= currentFrame();
2931 if (!part
->inherits("KHTMLPart") )
2933 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2936 static_cast<KHTMLPart
*>( part
)->findTextNext();
2939 void KHTMLPart::slotFindPrev()
2941 KParts::ReadOnlyPart
*part
= currentFrame();
2944 if (!part
->inherits("KHTMLPart") )
2946 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2949 static_cast<KHTMLPart
*>( part
)->findTextNext( true ); // reverse
2952 void KHTMLPart::slotFindDone()
2957 void KHTMLPart::slotFindAheadText()
2959 #ifndef KHTML_NO_TYPE_AHEAD_FIND
2960 KParts::ReadOnlyPart
*part
= currentFrame();
2963 if (!part
->inherits("KHTMLPart") )
2965 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2968 static_cast<KHTMLPart
*>( part
)->view()->startFindAhead( false );
2969 #endif // KHTML_NO_TYPE_AHEAD_FIND
2972 void KHTMLPart::slotFindAheadLink()
2974 #ifndef KHTML_NO_TYPE_AHEAD_FIND
2975 KParts::ReadOnlyPart
*part
= currentFrame();
2978 if (!part
->inherits("KHTMLPart") )
2980 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2983 static_cast<KHTMLPart
*>( part
)->view()->startFindAhead( true );
2984 #endif // KHTML_NO_TYPE_AHEAD_FIND
2987 void KHTMLPart::enableFindAheadActions( bool enable
)
2989 // only the topmost one has shortcuts
2990 KHTMLPart
* p
= this;
2991 while( p
->parentPart())
2992 p
= p
->parentPart();
2993 p
->d
->m_paFindAheadText
->setEnabled( enable
);
2994 p
->d
->m_paFindAheadLinks
->setEnabled( enable
);
2997 void KHTMLPart::slotFindDialogDestroyed()
3002 void KHTMLPart::findText()
3005 return parentPart()->findText();
3006 d
->m_find
.activate();
3009 void KHTMLPart::findText( const QString
&str
, long options
, QWidget
*parent
, KFindDialog
*findDialog
)
3012 return parentPart()->findText(str
, options
, parent
, findDialog
);
3013 d
->m_find
.createNewKFind(str
, options
, parent
, findDialog
);
3017 bool KHTMLPart::findTextNext( bool reverse
)
3020 return parentPart()->findTextNext( reverse
);
3021 return d
->m_find
.findTextNext( reverse
);
3024 QString
KHTMLPart::selectedTextAsHTML() const
3026 const Selection
&sel
= d
->editor_context
.m_selection
;
3027 if(!hasSelection()) {
3028 kDebug() << "Selection is not valid. Returning empty selection";
3031 if(sel
.start().offset() < 0 || sel
.end().offset() < 0) {
3032 kDebug() << "invalid values for end/startOffset " << sel
.start().offset() << " " << sel
.end().offset();
3035 DOM::Range r
= selection();
3036 if(r
.isNull() || r
.isDetached())
3038 int exceptioncode
= 0; //ignore the result
3039 return r
.handle()->toHTML(exceptioncode
).string();
3042 QString
KHTMLPart::selectedText() const
3044 bool hasNewLine
= true;
3045 bool seenTDTag
= false;
3047 const Selection
&sel
= d
->editor_context
.m_selection
;
3048 DOM::Node n
= sel
.start().node();
3049 while(!n
.isNull()) {
3050 if(n
.nodeType() == DOM::Node::TEXT_NODE
&& n
.handle()->renderer()) {
3051 DOM::DOMStringImpl
*dstr
= static_cast<DOM::TextImpl
*>(n
.handle())->renderString();
3052 QString
str(dstr
->s
, dstr
->l
);
3053 if(!str
.isEmpty()) {
3059 if(n
== sel
.start().node() && n
== sel
.end().node())
3060 text
= str
.mid(sel
.start().offset(), sel
.end().offset() - sel
.start().offset());
3061 else if(n
== sel
.start().node())
3062 text
= str
.mid(sel
.start().offset());
3063 else if(n
== sel
.end().node())
3064 text
+= str
.left(sel
.end().offset());
3070 // This is our simple HTML -> ASCII transformation:
3071 unsigned short id
= n
.elementId();
3074 text
+= static_cast<HTMLTextAreaElementImpl
*>(n
.handle())->value().string();
3077 if (static_cast<HTMLInputElementImpl
*>(n
.handle())->inputType() != HTMLInputElementImpl::PASSWORD
)
3078 text
+= static_cast<HTMLInputElementImpl
*>(n
.handle())->value().string();
3081 text
+= static_cast<HTMLSelectElementImpl
*>(n
.handle())->value().string();
3088 text
+= static_cast<HTMLImageElementImpl
*>(n
.handle())->altText().string();
3122 if(n
== sel
.end().node()) break;
3123 DOM::Node next
= n
.firstChild();
3124 if(next
.isNull()) next
= n
.nextSibling();
3125 while( next
.isNull() && !n
.parentNode().isNull() ) {
3127 next
= n
.nextSibling();
3128 unsigned short id
= n
.elementId();
3131 seenTDTag
= true; //Add two spaces after a td if then followed by text.
3173 int end
= text
.length();
3175 // Strip leading LFs
3176 while ((start
< end
) && (text
[start
] == '\n'))
3179 // Strip excessive trailing LFs
3180 while ((start
< (end
-1)) && (text
[end
-1] == '\n') && (text
[end
-2] == '\n'))
3183 return text
.mid(start
, end
-start
);
3186 QString
KHTMLPart::simplifiedSelectedText() const
3188 QString text
= selectedText();
3189 text
.replace(QChar(0xa0), ' ');
3190 // remove leading and trailing whitespace
3191 while (!text
.isEmpty() && text
[0].isSpace())
3193 while (!text
.isEmpty() && text
[text
.length()-1].isSpace())
3194 text
.truncate(text
.length()-1);
3198 bool KHTMLPart::hasSelection() const
3200 return !d
->editor_context
.m_selection
.isEmpty() && !d
->editor_context
.m_selection
.isCollapsed();
3203 DOM::Range
KHTMLPart::selection() const
3205 return d
->editor_context
.m_selection
.toRange();
3208 void KHTMLPart::selection(DOM::Node
&s
, long &so
, DOM::Node
&e
, long &eo
) const
3210 DOM::Range r
= d
->editor_context
.m_selection
.toRange();
3211 s
= r
.startContainer();
3212 so
= r
.startOffset();
3213 e
= r
.endContainer();
3217 void KHTMLPart::setSelection( const DOM::Range
&r
)
3222 const Selection
&KHTMLPart::caret() const
3224 return d
->editor_context
.m_selection
;
3227 const Selection
&KHTMLPart::dragCaret() const
3229 return d
->editor_context
.m_dragCaret
;
3232 void KHTMLPart::setCaret(const Selection
&s
, bool closeTyping
)
3234 if (d
->editor_context
.m_selection
!= s
) {
3235 clearCaretRectIfNeeded();
3236 setFocusNodeIfNeeded(s
);
3237 d
->editor_context
.m_selection
= s
;
3238 notifySelectionChanged(closeTyping
);
3242 void KHTMLPart::setDragCaret(const DOM::Selection
&dragCaret
)
3244 if (d
->editor_context
.m_dragCaret
!= dragCaret
) {
3245 d
->editor_context
.m_dragCaret
.needsCaretRepaint();
3246 d
->editor_context
.m_dragCaret
= dragCaret
;
3247 d
->editor_context
.m_dragCaret
.needsCaretRepaint();
3251 void KHTMLPart::clearSelection()
3253 clearCaretRectIfNeeded();
3254 setFocusNodeIfNeeded(d
->editor_context
.m_selection
);
3255 #ifdef APPLE_CHANGES
3256 d
->editor_context
.m_selection
.clear();
3258 d
->editor_context
.m_selection
.collapse();
3260 notifySelectionChanged();
3263 void KHTMLPart::invalidateSelection()
3265 clearCaretRectIfNeeded();
3266 d
->editor_context
.m_selection
.setNeedsLayout();
3267 selectionLayoutChanged();
3270 void KHTMLPart::setSelectionVisible(bool flag
)
3272 if (d
->editor_context
.m_caretVisible
== flag
)
3275 clearCaretRectIfNeeded();
3276 setFocusNodeIfNeeded(d
->editor_context
.m_selection
);
3277 d
->editor_context
.m_caretVisible
= flag
;
3278 // notifySelectionChanged();
3282 void KHTMLPart::slotClearSelection()
3285 && d
->editor_context
.m_selection
.state() != Selection::NONE
3286 && !d
->editor_context
.m_selection
.caretPos().node()->isContentEditable())
3287 clearCaretRectIfNeeded();
3288 bool hadSelection
= hasSelection();
3289 #ifdef APPLE_CHANGES
3290 d
->editor_context
.m_selection
.clear();
3292 d
->editor_context
.m_selection
.collapse();
3295 notifySelectionChanged();
3299 void KHTMLPart::clearCaretRectIfNeeded()
3301 if (d
->editor_context
.m_caretPaint
) {
3302 d
->editor_context
.m_caretPaint
= false;
3303 d
->editor_context
.m_selection
.needsCaretRepaint();
3307 void KHTMLPart::setFocusNodeIfNeeded(const Selection
&s
)
3309 if (!xmlDocImpl() || s
.state() == Selection::NONE
)
3312 NodeImpl
*n
= s
.start().node();
3313 NodeImpl
*target
= (n
&& n
->isContentEditable()) ? n
: 0;
3315 while (n
&& n
!= s
.end().node()) {
3316 if (n
->isContentEditable()) {
3320 n
= n
->traverseNextNode();
3323 assert(target
== 0 || target
->isContentEditable());
3326 for ( ; target
&& !target
->isFocusable(); target
= target
->parentNode())
3328 if (target
&& target
->isMouseFocusable())
3329 xmlDocImpl()->setFocusNode(target
);
3330 else if (!target
|| !target
->focused())
3331 xmlDocImpl()->setFocusNode(0);
3335 void KHTMLPart::selectionLayoutChanged()
3337 // kill any caret blink timer now running
3338 if (d
->editor_context
.m_caretBlinkTimer
>= 0) {
3339 killTimer(d
->editor_context
.m_caretBlinkTimer
);
3340 d
->editor_context
.m_caretBlinkTimer
= -1;
3343 // see if a new caret blink timer needs to be started
3344 if (d
->editor_context
.m_caretVisible
3345 && d
->editor_context
.m_selection
.state() != Selection::NONE
) {
3346 d
->editor_context
.m_caretPaint
= isCaretMode()
3347 || d
->editor_context
.m_selection
.caretPos().node()->isContentEditable();
3348 if (d
->editor_context
.m_caretBlinks
&& d
->editor_context
.m_caretPaint
)
3349 d
->editor_context
.m_caretBlinkTimer
= startTimer(qApp
->cursorFlashTime() / 2);
3350 d
->editor_context
.m_selection
.needsCaretRepaint();
3354 d
->m_doc
->updateSelection();
3356 // Always clear the x position used for vertical arrow navigation.
3357 // It will be restored by the vertical arrow navigation code if necessary.
3358 d
->editor_context
.m_xPosForVerticalArrowNavigation
= d
->editor_context
.NoXPosForVerticalArrowNavigation
;
3361 void KHTMLPart::notifySelectionChanged(bool closeTyping
)
3363 Editor
*ed
= d
->editor_context
.m_editor
;
3364 selectionLayoutChanged();
3366 ed
->clearTypingStyle();
3369 khtml::TypingCommand::closeTyping(ed
->lastEditCommand());
3372 emitSelectionChanged();
3376 void KHTMLPart::timerEvent(QTimerEvent
*e
)
3378 if (e
->timerId() == d
->editor_context
.m_caretBlinkTimer
) {
3379 if (d
->editor_context
.m_caretBlinks
&&
3380 d
->editor_context
.m_selection
.state() != Selection::NONE
) {
3381 d
->editor_context
.m_caretPaint
= !d
->editor_context
.m_caretPaint
;
3382 d
->editor_context
.m_selection
.needsCaretRepaint();
3384 } else if (e
->timerId() == d
->m_DNSPrefetchTimer
) {
3385 // kDebug( 6050 ) << "will lookup " << d->m_DNSPrefetchQueue.head() << d->m_numDNSPrefetchedNames;
3386 KIO::HostInfo::prefetchHost( d
->m_DNSPrefetchQueue
.dequeue() );
3387 if (d
->m_DNSPrefetchQueue
.isEmpty()) {
3388 killTimer( d
->m_DNSPrefetchTimer
);
3389 d
->m_DNSPrefetchTimer
= -1;
3391 } else if (e
->timerId() == d
->m_DNSTTLTimer
) {
3392 foreach (QString name
, d
->m_lookedupHosts
)
3393 d
->m_DNSPrefetchQueue
.enqueue(name
);
3394 if (d
->m_DNSPrefetchTimer
<= 0)
3395 d
->m_DNSPrefetchTimer
= startTimer( sDNSPrefetchTimerDelay
);
3399 bool KHTMLPart::mayPrefetchHostname( const QString
& name
)
3401 if (d
->m_bDNSPrefetch
== DNSPrefetchDisabled
)
3404 if (d
->m_numDNSPrefetchedNames
>= sMaxDNSPrefetchPerPage
)
3407 if (d
->m_bDNSPrefetch
== DNSPrefetchOnlyWWWAndSLD
) {
3408 int dots
= name
.count('.');
3409 if (dots
> 2 || (dots
== 2 && !name
.startsWith("www.")))
3413 if ( d
->m_lookedupHosts
.contains( name
) )
3416 d
->m_DNSPrefetchQueue
.enqueue( name
);
3417 d
->m_lookedupHosts
.insert( name
);
3418 d
->m_numDNSPrefetchedNames
++;
3420 if (d
->m_DNSPrefetchTimer
< 1)
3421 d
->m_DNSPrefetchTimer
= startTimer( sDNSPrefetchTimerDelay
);
3422 if (d
->m_DNSTTLTimer
< 1)
3423 d
->m_DNSTTLTimer
= startTimer( sDNSTTLSeconds
*1000 + 1 );
3428 void KHTMLPart::paintCaret(QPainter
*p
, const QRect
&rect
) const
3430 if (d
->editor_context
.m_caretPaint
)
3431 d
->editor_context
.m_selection
.paintCaret(p
, rect
);
3434 void KHTMLPart::paintDragCaret(QPainter
*p
, const QRect
&rect
) const
3436 d
->editor_context
.m_dragCaret
.paintCaret(p
, rect
);
3439 DOM::Editor
*KHTMLPart::editor() const {
3440 if (!d
->editor_context
.m_editor
)
3441 const_cast<KHTMLPart
*>(this)->d
->editor_context
.m_editor
= new DOM::Editor(const_cast<KHTMLPart
*>(this));
3442 return d
->editor_context
.m_editor
;
3445 void KHTMLPart::resetHoverText()
3447 if( !d
->m_overURL
.isEmpty() ) // Only if we were showing a link
3449 d
->m_overURL
.clear();
3450 d
->m_overURLTarget
.clear();
3451 emit
onURL( QString() );
3452 // revert to default statusbar text
3453 setStatusBarText(QString(), BarHoverText
);
3454 emit d
->m_extension
->mouseOverInfo(KFileItem());
3458 void KHTMLPart::overURL( const QString
&url
, const QString
&target
, bool /*shiftPressed*/ )
3460 KUrl u
= completeURL(url
);
3462 // special case for <a href="">
3463 if ( url
.isEmpty() )
3464 u
.setFileName( url
);
3468 if ( url
.isEmpty() ) {
3469 setStatusBarText(Qt::escape(u
.prettyUrl()), BarHoverText
);
3473 if ( d
->isJavaScriptURL(url
) ) {
3474 QString jscode
= d
->codeForJavaScriptURL( url
);
3475 jscode
= KStringHandler::rsqueeze( jscode
, 80 ); // truncate if too long
3476 if (url
.startsWith("javascript:window.open"))
3477 jscode
+= i18n(" (In new window)");
3478 setStatusBarText( Qt::escape( jscode
), BarHoverText
);
3482 KFileItem
item(u
, QString(), KFileItem::Unknown
);
3483 emit d
->m_extension
->mouseOverInfo(item
);
3487 KMimeType::Ptr typ
= KMimeType::findByUrl( u
);
3490 com
= typ
->comment( u
);
3492 if ( !u
.isValid() ) {
3493 setStatusBarText(Qt::escape(u
.prettyUrl()), BarHoverText
);
3497 if ( u
.isLocalFile() )
3499 // TODO : use KIO::stat() and create a KFileItem out of its result,
3500 // to use KFileItem::statusBarText()
3501 QByteArray path
= QFile::encodeName( u
.path() );
3503 KDE_struct_stat buff
;
3504 bool ok
= !KDE_stat( path
.data(), &buff
);
3506 KDE_struct_stat lbuff
;
3507 if (ok
) ok
= !KDE_lstat( path
.data(), &lbuff
);
3509 QString text
= Qt::escape(u
.prettyUrl());
3510 QString text2
= text
;
3512 if (ok
&& S_ISLNK( lbuff
.st_mode
) )
3516 tmp
= i18n( "Symbolic Link");
3518 tmp
= i18n("%1 (Link)", com
);
3519 char buff_two
[1024];
3521 int n
= readlink ( path
.data(), buff_two
, 1022);
3526 setStatusBarText(text2
, BarHoverText
);
3535 else if ( ok
&& S_ISREG( buff
.st_mode
) )
3537 if (buff
.st_size
< 1024)
3538 text
= i18n("%2 (%1 bytes)", (long) buff
.st_size
, text2
); // always put the URL last, in case it contains '%'
3541 float d
= (float) buff
.st_size
/1024.0;
3542 text
= i18n("%2 (%1 K)", KGlobal::locale()->formatNumber(d
, 2), text2
); // was %.2f
3547 else if ( ok
&& S_ISDIR( buff
.st_mode
) )
3557 setStatusBarText(text
, BarHoverText
);
3562 if (target
.toLower() == "_blank")
3564 extra
= i18n(" (In new window)");
3566 else if (!target
.isEmpty() &&
3567 (target
.toLower() != "_top") &&
3568 (target
.toLower() != "_self") &&
3569 (target
.toLower() != "_parent"))
3571 KHTMLPart
*p
= this;
3572 while (p
->parentPart())
3573 p
= p
->parentPart();
3574 if (!p
->frameExists(target
))
3575 extra
= i18n(" (In new window)");
3577 extra
= i18n(" (In other frame)");
3580 if (u
.protocol() == QLatin1String("mailto")) {
3581 QString mailtoMsg
/* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
3582 mailtoMsg
+= i18n("Email to: ") + KUrl::fromPercentEncoding(u
.path().toLatin1());
3583 const QStringList queries
= u
.query().mid(1).split('&');
3584 QStringList::ConstIterator it
= queries
.begin();
3585 const QStringList::ConstIterator itEnd
= queries
.end();
3586 for (; it
!= itEnd
; ++it
)
3587 if ((*it
).startsWith(QLatin1String("subject=")))
3588 mailtoMsg
+= i18n(" - Subject: ") + KUrl::fromPercentEncoding((*it
).mid(8).toLatin1());
3589 else if ((*it
).startsWith(QLatin1String("cc=")))
3590 mailtoMsg
+= i18n(" - CC: ") + KUrl::fromPercentEncoding((*it
).mid(3).toLatin1());
3591 else if ((*it
).startsWith(QLatin1String("bcc=")))
3592 mailtoMsg
+= i18n(" - BCC: ") + KUrl::fromPercentEncoding((*it
).mid(4).toLatin1());
3593 mailtoMsg
= Qt::escape(mailtoMsg
);
3594 mailtoMsg
.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString());
3595 setStatusBarText("<qt>"+mailtoMsg
, BarHoverText
);
3598 // Is this check necessary at all? (Frerich)
3600 else if (u
.protocol() == QLatin1String("http")) {
3601 DOM::Node hrefNode
= nodeUnderMouse().parentNode();
3602 while (hrefNode
.nodeName().string() != QLatin1String("A") && !hrefNode
.isNull())
3603 hrefNode
= hrefNode
.parentNode();
3605 if (!hrefNode
.isNull()) {
3606 DOM::Node hreflangNode
= hrefNode
.attributes().getNamedItem("HREFLANG");
3607 if (!hreflangNode
.isNull()) {
3608 QString countryCode
= hreflangNode
.nodeValue().string().toLower();
3609 // Map the language code to an appropriate country code.
3610 if (countryCode
== QLatin1String("en"))
3611 countryCode
= QLatin1String("gb");
3612 QString flagImg
= QLatin1String("<img src=%1>").arg(
3613 locate("locale", QLatin1String("l10n/")
3615 + QLatin1String("/flag.png")));
3616 emit
setStatusBarText(flagImg
+ u
.prettyUrl() + extra
);
3621 setStatusBarText(Qt::escape(u
.prettyUrl()) + extra
, BarHoverText
);
3626 // This executes in the active part on a click or other url selection action in
3627 // that active part.
3629 bool KHTMLPart::urlSelected( const QString
&url
, int button
, int state
, const QString
&_target
, const KParts::OpenUrlArguments
& _args
, const KParts::BrowserArguments
& _browserArgs
)
3631 KParts::OpenUrlArguments args
= _args
;
3632 KParts::BrowserArguments browserArgs
= _browserArgs
;
3633 bool hasTarget
= false;
3635 QString target
= _target
;
3636 if ( target
.isEmpty() && d
->m_doc
)
3637 target
= d
->m_doc
->baseTarget();
3638 if ( !target
.isEmpty() )
3641 if ( d
->isJavaScriptURL(url
) )
3643 crossFrameExecuteScript( target
, d
->codeForJavaScriptURL(url
) );
3647 KUrl cURL
= completeURL(url
);
3648 // special case for <a href=""> (IE removes filename, mozilla doesn't)
3649 if ( url
.isEmpty() )
3650 cURL
.setFileName( url
); // removes filename
3652 if ( !cURL
.isValid() )
3653 // ### ERROR HANDLING
3656 kDebug(6050) << this << "complete URL:" << cURL
.url() << "target=" << target
;
3658 if ( state
& Qt::ControlModifier
)
3660 browserArgs
.setNewTab(true);
3661 emit d
->m_extension
->createNewWindow( cURL
, args
, browserArgs
);
3665 if ( button
== Qt::LeftButton
&& ( state
& Qt::ShiftModifier
) )
3667 KIO::MetaData metaData
;
3668 metaData
.insert( "referrer", d
->m_referrer
);
3669 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n( "Save As" ), cURL
, metaData
);
3673 if (!checkLinkSecurity(cURL
,
3674 ki18n( "<qt>This untrusted page links to<br /><b>%1</b>.<br />Do you want to follow the link?</qt>" ),
3678 browserArgs
.frameName
= target
;
3680 args
.metaData().insert("main_frame_request",
3681 parentPart() == 0 ? "TRUE":"FALSE");
3682 args
.metaData().insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
3683 args
.metaData().insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
3684 args
.metaData().insert("PropagateHttpHeader", "true");
3685 args
.metaData().insert("ssl_was_in_use", d
->m_ssl_in_use
? "TRUE":"FALSE");
3686 args
.metaData().insert("ssl_activate_warnings", "TRUE");
3688 if ( hasTarget
&& target
!= "_self" && target
!= "_top" && target
!= "_blank" && target
!= "_parent" )
3690 // unknown frame names should open in a new window.
3691 khtml::ChildFrame
*frame
= recursiveFrameRequest( this, cURL
, args
, browserArgs
, false );
3694 args
.metaData()["referrer"] = d
->m_referrer
;
3695 requestObject( frame
, cURL
, args
, browserArgs
);
3700 if (!d
->m_referrer
.isEmpty() && !args
.metaData().contains("referrer"))
3701 args
.metaData()["referrer"] = d
->m_referrer
;
3703 if ( button
== Qt::NoButton
&& (state
& Qt::ShiftModifier
) && (state
& Qt::ControlModifier
) )
3705 emit d
->m_extension
->createNewWindow( cURL
, args
, browserArgs
);
3709 if ( state
& Qt::ShiftModifier
)
3711 KParts::WindowArgs winArgs
;
3712 winArgs
.setLowerWindow(true);
3713 emit d
->m_extension
->createNewWindow( cURL
, args
, browserArgs
, winArgs
);
3717 //If we're asked to open up an anchor in the current URL, in current window,
3718 //merely gotoanchor, and do not reload the new page. Note that this does
3719 //not apply if the URL is the same page, but without a ref
3720 if (cURL
.hasRef() && (!hasTarget
|| target
== "_self"))
3722 if (d
->isLocalAnchorJump(cURL
))
3724 d
->executeAnchorJump(cURL
, browserArgs
.lockHistory() );
3725 return false; // we jumped, but we didn't open a URL
3729 if ( !d
->m_bComplete
&& !hasTarget
)
3732 view()->viewport()->unsetCursor();
3733 emit d
->m_extension
->openUrlRequest( cURL
, args
, browserArgs
);
3737 void KHTMLPart::slotViewDocumentSource()
3739 KUrl
currentUrl(this->url());
3740 bool isTempFile
= false;
3741 if (!(currentUrl
.isLocalFile()) && KHTMLPageCache::self()->isComplete(d
->m_cacheId
))
3743 KTemporaryFile sourceFile
;
3744 sourceFile
.setSuffix(defaultExtension());
3745 sourceFile
.setAutoRemove(false);
3746 if (sourceFile
.open())
3748 QDataStream
stream ( &sourceFile
);
3749 KHTMLPageCache::self()->saveData(d
->m_cacheId
, &stream
);
3750 currentUrl
= KUrl();
3751 currentUrl
.setPath(sourceFile
.fileName());
3756 (void) KRun::runUrl( currentUrl
, QLatin1String("text/plain"), view(), isTempFile
);
3759 void KHTMLPart::slotViewPageInfo()
3763 QDialog
*dlg
= new QDialog(0);
3764 dlg
->setAttribute(Qt::WA_DeleteOnClose
);
3765 dlg
->setObjectName("KHTML Page Info Dialog");
3768 ui
._close
->setGuiItem(KStandardGuiItem::close());
3770 connect(ui
._close
, SIGNAL(clicked()), dlg
, SLOT(accept()));
3772 ui
._title
->setText(d
->m_doc
->title().string());
3774 // If it's a frame, set the caption to "Frame Information"
3775 if ( parentPart() && d
->m_doc
&& d
->m_doc
->isHTMLDocument() ) {
3776 dlg
->setWindowTitle(i18n("Frame Information"));
3781 if (!d
->m_pageServices
.isEmpty())
3782 editStr
= i18n(" <a href=\"%1\">[Properties]</a>", d
->m_pageServices
);
3784 QString squeezedURL
= KStringHandler::csqueeze( url().prettyUrl(), 80 );
3785 ui
._url
->setText("<a href=\"" + url().url() + "\">" + squeezedURL
+ "</a>" + editStr
);
3786 if (lastModified().isEmpty())
3788 ui
._lastModified
->hide();
3789 ui
._lmLabel
->hide();
3792 ui
._lastModified
->setText(lastModified());
3794 const QString
& enc
= encoding();
3795 if (enc
.isEmpty()) {
3797 ui
._encoding
->hide();
3799 ui
._encoding
->setText(enc
);
3801 /* populate the list view now */
3802 const QStringList headers
= d
->m_httpHeaders
.split("\n");
3804 QStringList::ConstIterator it
= headers
.begin();
3805 const QStringList::ConstIterator itEnd
= headers
.end();
3807 for (; it
!= itEnd
; ++it
) {
3808 const QStringList header
= (*it
).split(QRegExp(":[ ]+"));
3809 if (header
.count() != 2)
3811 QTreeWidgetItem
*item
= new QTreeWidgetItem(ui
._headers
);
3812 item
->setText(0, header
[0]);
3813 item
->setText(1, header
[1]);
3817 /* put no code here */
3821 void KHTMLPart::slotViewFrameSource()
3823 KParts::ReadOnlyPart
*frame
= currentFrame();
3827 KUrl url
= frame
->url();
3828 bool isTempFile
= false;
3829 if (!(url
.isLocalFile()) && frame
->inherits("KHTMLPart"))
3831 long cacheId
= static_cast<KHTMLPart
*>(frame
)->d
->m_cacheId
;
3833 if (KHTMLPageCache::self()->isComplete(cacheId
))
3835 KTemporaryFile sourceFile
;
3836 sourceFile
.setSuffix(defaultExtension());
3837 sourceFile
.setAutoRemove(false);
3838 if (sourceFile
.open())
3840 QDataStream
stream ( &sourceFile
);
3841 KHTMLPageCache::self()->saveData(cacheId
, &stream
);
3843 url
.setPath(sourceFile
.fileName());
3849 (void) KRun::runUrl( url
, QLatin1String("text/plain"), view(), isTempFile
);
3852 KUrl
KHTMLPart::backgroundURL() const
3854 // ### what about XML documents? get from CSS?
3855 if (!d
->m_doc
|| !d
->m_doc
->isHTMLDocument())
3858 QString relURL
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body()->getAttribute( ATTR_BACKGROUND
).string();
3860 return KUrl( url(), relURL
);
3863 void KHTMLPart::slotSaveBackground()
3865 KIO::MetaData metaData
;
3866 metaData
["referrer"] = d
->m_referrer
;
3867 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n("Save Background Image As"), backgroundURL(), metaData
);
3870 void KHTMLPart::slotSaveDocument()
3872 KUrl
srcURL( url() );
3874 if ( srcURL
.fileName(KUrl::ObeyTrailingSlash
).isEmpty() )
3875 srcURL
.setFileName( "index" + defaultExtension() );
3877 KIO::MetaData metaData
;
3879 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n( "Save As" ), srcURL
, metaData
, "text/html", d
->m_cacheId
);
3882 void KHTMLPart::slotSecurity()
3884 // kDebug( 6050 ) << "Meta Data:" << endl
3885 // << d->m_ssl_peer_cert_subject
3887 // << d->m_ssl_peer_cert_issuer
3889 // << d->m_ssl_cipher
3891 // << d->m_ssl_cipher_desc
3893 // << d->m_ssl_cipher_version
3895 // << d->m_ssl_good_from
3897 // << d->m_ssl_good_until
3899 // << d->m_ssl_cert_state
3902 //### reenable with new signature
3904 KSSLInfoDialog
*kid
= new KSSLInfoDialog(d
->m_ssl_in_use
, widget(), "kssl_info_dlg", true );
3906 const QStringList sl
= d
->m_ssl_peer_chain
.split('\n', QString::SkipEmptyParts
);
3907 QList
<QSslCertificate
> certChain
;
3908 bool certChainOk
= d
->m_ssl_in_use
;
3910 foreach (const QString
&s
, sl
) {
3911 certChain
.append(QSslCertificate(s
.toAscii())); //or is it toLocal8Bit or whatever?
3912 if (certChain
.last().isNull()) {
3913 certChainOk
= false;
3919 kid
->setup(certChain
,
3923 d
->m_ssl_cipher_desc
,
3924 d
->m_ssl_cipher_version
,
3925 d
->m_ssl_cipher_used_bits
.toInt(),
3926 d
->m_ssl_cipher_bits
.toInt(),
3927 (KSSLCertificate::KSSLValidation
) d
->m_ssl_cert_state
.toInt());
3930 //the dialog deletes itself on close
3933 KSSLInfoDialog
*kid
= new KSSLInfoDialog(0);
3934 //### This is boilerplate code and it's copied from SlaveInterface.
3935 QStringList sl
= d
->m_ssl_peer_chain
.split('\x01', QString::SkipEmptyParts
);
3936 QList
<QSslCertificate
> certChain
;
3937 bool decodedOk
= true;
3938 foreach (const QString
&s
, sl
) {
3939 certChain
.append(QSslCertificate(s
.toAscii())); //or is it toLocal8Bit or whatever?
3940 if (certChain
.last().isNull()) {
3946 if (decodedOk
|| true /*H4X*/) {
3947 kid
->setSslInfo(certChain
,
3950 d
->m_ssl_protocol_version
,
3952 d
->m_ssl_cipher_used_bits
.toInt(),
3953 d
->m_ssl_cipher_bits
.toInt(),
3954 KSSLInfoDialog::errorsFromString(d
->m_ssl_cert_errors
));
3955 kDebug(7024) << "Showing SSL Info dialog";
3957 kDebug(7024) << "SSL Info dialog closed";
3959 KMessageBox::information(0, i18n("The peer SSL certificate chain "
3960 "appears to be corrupt."),
3965 void KHTMLPart::slotSaveFrame()
3967 KParts::ReadOnlyPart
*frame
= currentFrame();
3971 KUrl
srcURL( frame
->url() );
3973 if ( srcURL
.fileName(KUrl::ObeyTrailingSlash
).isEmpty() )
3974 srcURL
.setFileName( "index" + defaultExtension() );
3976 KIO::MetaData metaData
;
3977 // Referrer unknown?
3978 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n( "Save Frame As" ), srcURL
, metaData
, "text/html" );
3981 void KHTMLPart::slotSetEncoding(const QString
&enc
)
3983 d
->m_autoDetectLanguage
=KEncodingDetector::None
;
3984 setEncoding( enc
, true);
3987 void KHTMLPart::slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript scri
)
3989 d
->m_autoDetectLanguage
=scri
;
3990 setEncoding( QString(), false );
3993 void KHTMLPart::slotUseStylesheet()
3997 bool autoselect
= (d
->m_paUseStylesheet
->currentItem() == 0);
3998 d
->m_sheetUsed
= autoselect
? QString() : d
->m_paUseStylesheet
->currentText();
3999 d
->m_doc
->updateStyleSelector();
4003 void KHTMLPart::updateActions()
4005 bool frames
= false;
4007 QList
<khtml::ChildFrame
*>::ConstIterator it
= d
->m_frames
.constBegin();
4008 const QList
<khtml::ChildFrame
*>::ConstIterator end
= d
->m_frames
.constEnd();
4009 for (; it
!= end
; ++it
)
4010 if ( (*it
)->m_type
== khtml::ChildFrame::Frame
)
4016 if (d
->m_paViewFrame
)
4017 d
->m_paViewFrame
->setEnabled( frames
);
4018 if (d
->m_paSaveFrame
)
4019 d
->m_paSaveFrame
->setEnabled( frames
);
4022 d
->m_paFind
->setText( i18n( "&Find in Frame..." ) );
4024 d
->m_paFind
->setText( i18n( "&Find..." ) );
4026 KParts::Part
*frame
= 0;
4029 frame
= currentFrame();
4031 bool enableFindAndSelectAll
= true;
4034 enableFindAndSelectAll
= frame
->inherits( "KHTMLPart" );
4036 d
->m_paFind
->setEnabled( enableFindAndSelectAll
);
4037 d
->m_paSelectAll
->setEnabled( enableFindAndSelectAll
);
4039 bool enablePrintFrame
= false;
4043 QObject
*ext
= KParts::BrowserExtension::childObject( frame
);
4045 enablePrintFrame
= ext
->metaObject()->indexOfSlot( "print()" ) != -1;
4048 d
->m_paPrintFrame
->setEnabled( enablePrintFrame
);
4053 if ( d
->m_doc
&& d
->m_doc
->isHTMLDocument() && static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body() && !d
->m_bClearing
)
4054 bgURL
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body()->getAttribute( ATTR_BACKGROUND
).string();
4056 if (d
->m_paSaveBackground
)
4057 d
->m_paSaveBackground
->setEnabled( !bgURL
.isEmpty() );
4059 if ( d
->m_paDebugScript
)
4060 d
->m_paDebugScript
->setEnabled( d
->m_frame
? d
->m_frame
->m_jscript
: 0L );
4063 KParts::LiveConnectExtension
*KHTMLPart::liveConnectExtension( const DOM::NodeImpl
*frame
) {
4064 const ConstFrameIt end
= d
->m_objects
.constEnd();
4065 for(ConstFrameIt it
= d
->m_objects
.constBegin(); it
!= end
; ++it
)
4066 if ((*it
)->m_partContainerElement
== frame
)
4067 return (*it
)->m_liveconnect
;
4071 bool KHTMLPart::requestFrame( DOM::HTMLPartContainerElementImpl
*frame
, const QString
&url
,
4072 const QString
&frameName
, const QStringList
¶ms
, bool isIFrame
)
4074 //kDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )";
4075 FrameIt it
= d
->m_frames
.find( frameName
);
4076 if ( it
== d
->m_frames
.end() )
4078 khtml::ChildFrame
* child
= new khtml::ChildFrame
;
4079 //kDebug( 6050 ) << "inserting new frame into frame map " << frameName;
4080 child
->m_name
= frameName
;
4081 it
= d
->m_frames
.insert( d
->m_frames
.end(), child
);
4084 (*it
)->m_type
= isIFrame
? khtml::ChildFrame::IFrame
: khtml::ChildFrame::Frame
;
4085 (*it
)->m_partContainerElement
= frame
;
4086 (*it
)->m_params
= params
;
4088 // Support for <frame src="javascript:string">
4089 if ( d
->isJavaScriptURL(url
) )
4091 if ( processObjectRequest(*it
, KUrl("about:blank"), QString("text/html") ) ) {
4092 KHTMLPart
* p
= static_cast<KHTMLPart
*>(static_cast<KParts::ReadOnlyPart
*>((*it
)->m_part
));
4094 // See if we want to replace content with javascript: output..
4095 QVariant res
= p
->executeScript( DOM::Node(),
4096 d
->codeForJavaScriptURL(url
) );
4097 if ( res
.type() == QVariant::String
&& p
->d
->m_redirectURL
.isEmpty() ) {
4099 // We recreated the document, so propagate domain again.
4100 d
->propagateInitialDomainTo( p
);
4101 p
->write( res
.toString() );
4108 KUrl u
= url
.isEmpty() ? KUrl() : completeURL( url
);
4109 return requestObject( *it
, u
);
4112 QString
KHTMLPart::requestFrameName()
4114 return QString::fromLatin1("<!--frame %1-->").arg(d
->m_frameNameId
++);
4117 bool KHTMLPart::requestObject( DOM::HTMLPartContainerElementImpl
*frame
, const QString
&url
,
4118 const QString
&serviceType
, const QStringList
¶ms
)
4120 //kDebug( 6005 ) << this << "frame=" << frame;
4121 khtml::ChildFrame
*child
= new khtml::ChildFrame
;
4122 FrameIt it
= d
->m_objects
.insert( d
->m_objects
.end(), child
);
4123 (*it
)->m_partContainerElement
= frame
;
4124 (*it
)->m_type
= khtml::ChildFrame::Object
;
4125 (*it
)->m_params
= params
;
4127 KParts::OpenUrlArguments args
;
4128 args
.setMimeType(serviceType
);
4129 if (!requestObject( *it
, completeURL( url
), args
) && !(*it
)->m_run
) {
4130 (*it
)->m_bCompleted
= true;
4136 bool KHTMLPart::requestObject( khtml::ChildFrame
*child
, const KUrl
&url
, const KParts::OpenUrlArguments
&_args
,
4137 const KParts::BrowserArguments
& browserArgs
)
4139 if (!checkLinkSecurity(url
))
4141 kDebug(6005) << this << "checkLinkSecurity refused";
4144 if ( child
->m_bPreloaded
)
4146 kDebug(6005) << "preload";
4147 if ( child
->m_partContainerElement
&& child
->m_part
)
4148 child
->m_partContainerElement
->setWidget( child
->m_part
->widget() );
4150 child
->m_bPreloaded
= false;
4154 //kDebug(6005) << "child=" << child << "child->m_part=" << child->m_part;
4156 KParts::OpenUrlArguments
args( _args
);
4159 child
->m_run
->abort();
4161 if ( child
->m_part
&& !args
.reload() && urlcmp( child
->m_part
->url().url(), url
.url(), KUrl::CompareWithoutTrailingSlash
| KUrl::CompareWithoutFragment
) )
4162 args
.setMimeType(child
->m_serviceType
);
4164 child
->m_browserArgs
= browserArgs
;
4165 child
->m_args
= args
;
4166 child
->m_args
.setReload(d
->m_cachePolicy
== KIO::CC_Reload
);
4167 child
->m_serviceName
.clear();
4168 if (!d
->m_referrer
.isEmpty() && !child
->m_args
.metaData().contains( "referrer" ))
4169 child
->m_args
.metaData()["referrer"] = d
->m_referrer
;
4171 child
->m_args
.metaData().insert("PropagateHttpHeader", "true");
4172 child
->m_args
.metaData().insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
4173 child
->m_args
.metaData().insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
4174 child
->m_args
.metaData().insert("main_frame_request",
4175 parentPart() == 0 ? "TRUE":"FALSE");
4176 child
->m_args
.metaData().insert("ssl_was_in_use",
4177 d
->m_ssl_in_use
? "TRUE":"FALSE");
4178 child
->m_args
.metaData().insert("ssl_activate_warnings", "TRUE");
4179 child
->m_args
.metaData().insert("cross-domain", toplevelURL().url());
4181 // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
4182 if ((url
.isEmpty() || url
.url() == "about:blank") && args
.mimeType().isEmpty())
4183 args
.setMimeType(QLatin1String("text/html"));
4185 if ( args
.mimeType().isEmpty() ) {
4186 kDebug(6050) << "Running new KHTMLRun for" << this << "and child=" << child
;
4187 child
->m_run
= new KHTMLRun( this, child
, url
, child
->m_args
, child
->m_browserArgs
, true );
4188 d
->m_bComplete
= false; // ensures we stop it in checkCompleted...
4191 return processObjectRequest( child
, url
, args
.mimeType() );
4195 void KHTMLPart::childLoadFailure( khtml::ChildFrame
*child
)
4197 child
->m_bCompleted
= true;
4198 if ( child
->m_partContainerElement
)
4199 child
->m_partContainerElement
->partLoadingErrorNotify();
4204 bool KHTMLPart::processObjectRequest( khtml::ChildFrame
*child
, const KUrl
&_url
, const QString
&mimetype
)
4206 //kDebug( 6050 ) << "trying to create part for" << mimetype;
4208 // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
4209 // by an emitting frame part (emit openUrlRequest( blahurl, ... ) . A few lines below we delete the part
4210 // though -> the reference becomes invalid -> crash is likely
4213 // khtmlrun called us this way to indicate a loading error
4214 if ( d
->m_onlyLocalReferences
|| ( url
.isEmpty() && mimetype
.isEmpty() ) )
4216 childLoadFailure(child
);
4220 if (child
->m_bNotify
)
4222 child
->m_bNotify
= false;
4223 if ( !child
->m_browserArgs
.lockHistory() )
4224 emit d
->m_extension
->openUrlNotify();
4227 if ( child
->m_serviceType
!= mimetype
|| !child
->m_part
|| (child
->m_run
&& child
->m_run
->serverSuggestsSave()))
4229 // We often get here if we didn't know the mimetype in advance, and had to rely
4230 // on KRun to figure it out. In this case, we let the element check if it wants to
4231 // handle this mimetype itself, for e.g. images.
4232 if ( child
->m_partContainerElement
&&
4233 child
->m_partContainerElement
->mimetypeHandledInternally(mimetype
) ) {
4234 child
->m_bCompleted
= true;
4239 // Before attempting to load a part, check if the user wants that.
4240 // Many don't like getting ZIP files embedded.
4241 // However we don't want to ask for flash and other plugin things..
4242 if ( child
->m_type
!= khtml::ChildFrame::Object
&& child
->m_type
!= khtml::ChildFrame::IFrame
)
4244 QString suggestedFileName
;
4245 int disposition
= 0;
4246 if ( child
->m_run
) {
4247 suggestedFileName
= child
->m_run
->suggestedFileName();
4248 disposition
= (child
->m_run
->serverSuggestsSave()) ? KParts::BrowserRun::AttachmentDisposition
: KParts::BrowserRun::InlineDisposition
;
4251 KParts::BrowserRun::AskSaveResult res
= KParts::BrowserRun::askEmbedOrSave(
4252 url
, mimetype
, suggestedFileName
, disposition
);
4254 case KParts::BrowserRun::Save
:
4255 KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url
, child
->m_args
.metaData(), QString(), 0, suggestedFileName
);
4257 case KParts::BrowserRun::Cancel
:
4258 child
->m_bCompleted
= true;
4260 return true; // done
4266 KMimeType::Ptr mime
= KMimeType::mimeType(mimetype
);
4268 // If KHTMLPart can handle the frame, then let's force using it, even
4269 // if the normally preferred part is another one, so that cross-frame
4270 // scripting can work.
4271 if (mime
->is("text/html")
4272 || mime
->is("application/xml")) { // this includes xhtml and svg
4273 child
->m_serviceName
= "khtml";
4277 QStringList dummy
; // the list of servicetypes handled by the part is now unused.
4278 KParts::ReadOnlyPart
*part
= createPart( d
->m_view
->viewport(), this, mimetype
, child
->m_serviceName
, dummy
, child
->m_params
);
4282 childLoadFailure(child
);
4286 part
->setObjectName( child
->m_name
);
4289 if ( child
->m_part
)
4291 if (!qobject_cast
<KHTMLPart
*>(child
->m_part
) && child
->m_jscript
)
4292 child
->m_jscript
->clear();
4293 partManager()->removePart( (KParts::ReadOnlyPart
*)child
->m_part
);
4294 delete (KParts::ReadOnlyPart
*)child
->m_part
;
4295 if (child
->m_liveconnect
) {
4296 disconnect(child
->m_liveconnect
, SIGNAL(partEvent(const unsigned long, const QString
&, const KParts::LiveConnectExtension::ArgList
&)), child
, SLOT(liveConnectEvent(const unsigned long, const QString
&, const KParts::LiveConnectExtension::ArgList
&)));
4297 child
->m_liveconnect
= 0L;
4301 child
->m_serviceType
= mimetype
;
4302 if ( child
->m_partContainerElement
&& part
->widget() )
4303 child
->m_partContainerElement
->setWidget( part
->widget() );
4305 if ( child
->m_type
!= khtml::ChildFrame::Object
)
4306 partManager()->addPart( part
, false );
4308 // kDebug(6005) << "AH! NO FRAME!!!!!";
4310 child
->m_part
= part
;
4312 if (qobject_cast
<KHTMLPart
*>(part
)) {
4313 static_cast<KHTMLPart
*>(part
)->d
->m_frame
= child
;
4314 } else if (child
->m_partContainerElement
) {
4315 child
->m_liveconnect
= KParts::LiveConnectExtension::childObject(part
);
4316 if (child
->m_liveconnect
)
4317 connect(child
->m_liveconnect
, SIGNAL(partEvent(const unsigned long, const QString
&, const KParts::LiveConnectExtension::ArgList
&)), child
, SLOT(liveConnectEvent(const unsigned long, const QString
&, const KParts::LiveConnectExtension::ArgList
&)));
4319 KParts::StatusBarExtension
*sb
= KParts::StatusBarExtension::childObject(part
);
4321 sb
->setStatusBar( d
->m_statusBarExtension
->statusBar() );
4323 connect( part
, SIGNAL( started( KIO::Job
*) ),
4324 this, SLOT( slotChildStarted( KIO::Job
*) ) );
4325 connect( part
, SIGNAL( completed() ),
4326 this, SLOT( slotChildCompleted() ) );
4327 connect( part
, SIGNAL( completed(bool) ),
4328 this, SLOT( slotChildCompleted(bool) ) );
4329 connect( part
, SIGNAL( setStatusBarText( const QString
& ) ),
4330 this, SIGNAL( setStatusBarText( const QString
& ) ) );
4331 if ( part
->inherits( "KHTMLPart" ) )
4333 connect( this, SIGNAL( completed() ),
4334 part
, SLOT( slotParentCompleted() ) );
4335 connect( this, SIGNAL( completed(bool) ),
4336 part
, SLOT( slotParentCompleted() ) );
4337 // As soon as the child's document is created, we need to set its domain
4338 // (but we do so only once, so it can't be simply done in the child)
4339 connect( part
, SIGNAL( docCreated() ),
4340 this, SLOT( slotChildDocCreated() ) );
4343 child
->m_extension
= KParts::BrowserExtension::childObject( part
);
4345 if ( child
->m_extension
)
4347 connect( child
->m_extension
, SIGNAL( openUrlNotify() ),
4348 d
->m_extension
, SIGNAL( openUrlNotify() ) );
4350 connect( child
->m_extension
, SIGNAL( openUrlRequestDelayed( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
& ) ),
4351 this, SLOT( slotChildURLRequest( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
& ) ) );
4353 connect( child
->m_extension
, SIGNAL( createNewWindow( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
&, const KParts::WindowArgs
&, KParts::ReadOnlyPart
** ) ),
4354 d
->m_extension
, SIGNAL( createNewWindow( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
& , const KParts::WindowArgs
&, KParts::ReadOnlyPart
**) ) );
4356 connect( child
->m_extension
, SIGNAL(popupMenu(QPoint
,KFileItemList
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)),
4357 d
->m_extension
, SIGNAL(popupMenu(QPoint
,KFileItemList
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)) );
4358 connect( child
->m_extension
, SIGNAL(popupMenu(QPoint
,KUrl
,mode_t
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)),
4359 d
->m_extension
, SIGNAL(popupMenu(QPoint
,KUrl
,mode_t
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)) );
4361 connect( child
->m_extension
, SIGNAL( infoMessage( const QString
& ) ),
4362 d
->m_extension
, SIGNAL( infoMessage( const QString
& ) ) );
4364 connect( child
->m_extension
, SIGNAL( requestFocus( KParts::ReadOnlyPart
* ) ),
4365 this, SLOT( slotRequestFocus( KParts::ReadOnlyPart
* ) ) );
4367 child
->m_extension
->setBrowserInterface( d
->m_extension
->browserInterface() );
4370 else if ( child
->m_partContainerElement
&& child
->m_part
&&
4371 child
->m_partContainerElement
->childWidget() != child
->m_part
->widget() )
4372 child
->m_partContainerElement
->setWidget( child
->m_part
->widget() );
4374 checkEmitLoadEvent();
4375 // Some JS code in the load event may have destroyed the part
4376 // In that case, abort
4377 if ( !child
->m_part
)
4380 if ( child
->m_bPreloaded
)
4382 if ( child
->m_partContainerElement
&& child
->m_part
)
4383 child
->m_partContainerElement
->setWidget( child
->m_part
->widget() );
4385 child
->m_bPreloaded
= false;
4389 child
->m_args
.setReload(d
->m_cachePolicy
== KIO::CC_Reload
);
4391 // make sure the part has a way to find out about the mimetype.
4392 // we actually set it in child->m_args in requestObject already,
4393 // but it's useless if we had to use a KHTMLRun instance, as the
4394 // point the run object is to find out exactly the mimetype.
4395 child
->m_args
.setMimeType(mimetype
);
4397 // if not a frame set child as completed
4398 child
->m_bCompleted
= child
->m_type
== khtml::ChildFrame::Object
;
4400 if ( child
->m_part
) {
4401 child
->m_part
->setArguments( child
->m_args
);
4403 if ( child
->m_extension
) {
4404 child
->m_extension
->setBrowserArguments( child
->m_browserArgs
);
4407 if(url
.protocol() == "javascript" || url
.url() == "about:blank") {
4408 if (!child
->m_part
->inherits("KHTMLPart"))
4411 KHTMLPart
* p
= static_cast<KHTMLPart
*>(static_cast<KParts::ReadOnlyPart
*>(child
->m_part
));
4414 if (d
->m_doc
&& p
->d
->m_doc
)
4415 p
->d
->m_doc
->setBaseURL(d
->m_doc
->baseURL());
4417 // We may have to re-propagate the domain here if we go here due to navigation
4418 d
->propagateInitialDomainTo(p
);
4420 if (!url
.url().startsWith("about:")) {
4421 p
->write(url
.path());
4424 // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
4425 p
->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
4430 else if ( !url
.isEmpty() )
4432 //kDebug( 6050 ) << "opening" << url << "in frame" << child->m_part;
4433 bool b
= child
->m_part
->openUrl( url
);
4434 if (child
->m_bCompleted
)
4440 child
->m_bCompleted
= true;
4446 KParts::ReadOnlyPart
*KHTMLPart::createPart( QWidget
*parentWidget
,
4447 QObject
*parent
, const QString
&mimetype
,
4448 QString
&serviceName
, QStringList
&serviceTypes
,
4449 const QStringList
¶ms
)
4452 if ( !serviceName
.isEmpty() )
4453 constr
.append( QString::fromLatin1( "DesktopEntryName == '%1'" ).arg( serviceName
) );
4455 KService::List offers
= KMimeTypeTrader::self()->query( mimetype
, "KParts/ReadOnlyPart", constr
);
4457 if ( offers
.isEmpty() ) {
4458 int pos
= mimetype
.indexOf( "-plugin" );
4461 QString stripped_mime
= mimetype
.left( pos
);
4462 offers
= KMimeTypeTrader::self()->query( stripped_mime
, "KParts/ReadOnlyPart", constr
);
4463 if ( offers
.isEmpty() )
4467 KService::List::ConstIterator it
= offers
.constBegin();
4468 const KService::List::ConstIterator itEnd
= offers
.constEnd();
4469 for ( ; it
!= itEnd
; ++it
)
4471 KService::Ptr service
= (*it
);
4473 KPluginLoader
loader( *service
, KHTMLGlobal::componentData() );
4474 KPluginFactory
* const factory
= loader
.factory();
4476 // Turn params into a QVariantList as expected by KPluginFactory
4477 QVariantList variantlist
;
4478 Q_FOREACH(const QString
& str
, params
)
4479 variantlist
<< QVariant(str
);
4481 if ( service
->serviceTypes().contains( "Browser/View" ) )
4482 variantlist
<< QString("Browser/View");
4484 KParts::ReadOnlyPart
* part
= factory
->create
<KParts::ReadOnlyPart
>(parentWidget
, parent
, QString(), variantlist
);
4486 serviceTypes
= service
->serviceTypes();
4487 serviceName
= service
->name();
4491 // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
4492 kWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
4493 .arg(service
->name()).arg(loader
.errorString());
4499 KParts::PartManager
*KHTMLPart::partManager()
4501 if ( !d
->m_manager
&& d
->m_view
)
4503 d
->m_manager
= new KParts::PartManager( d
->m_view
->topLevelWidget(), this );
4504 d
->m_manager
->setObjectName( "khtml part manager" );
4505 d
->m_manager
->setAllowNestedParts( true );
4506 connect( d
->m_manager
, SIGNAL( activePartChanged( KParts::Part
* ) ),
4507 this, SLOT( slotActiveFrameChanged( KParts::Part
* ) ) );
4508 connect( d
->m_manager
, SIGNAL( partRemoved( KParts::Part
* ) ),
4509 this, SLOT( slotPartRemoved( KParts::Part
* ) ) );
4512 return d
->m_manager
;
4515 void KHTMLPart::submitFormAgain()
4517 disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
4518 if( d
->m_doc
&& !d
->m_doc
->parsing() && d
->m_submitForm
)
4519 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
);
4521 delete d
->m_submitForm
;
4522 d
->m_submitForm
= 0;
4525 void KHTMLPart::submitFormProxy( const char *action
, const QString
&url
, const QByteArray
&formData
, const QString
&_target
, const QString
& contentType
, const QString
& boundary
)
4527 submitForm(action
, url
, formData
, _target
, contentType
, boundary
);
4530 void KHTMLPart::submitForm( const char *action
, const QString
&url
, const QByteArray
&formData
, const QString
&_target
, const QString
& contentType
, const QString
& boundary
)
4532 kDebug(6000) << this << "target=" << _target
<< "url=" << url
;
4533 if (d
->m_formNotification
== KHTMLPart::Only
) {
4534 emit
formSubmitNotification(action
, url
, formData
, _target
, contentType
, boundary
);
4536 } else if (d
->m_formNotification
== KHTMLPart::Before
) {
4537 emit
formSubmitNotification(action
, url
, formData
, _target
, contentType
, boundary
);
4540 KUrl u
= completeURL( url
);
4544 // ### ERROR HANDLING!
4548 // Form security checks
4551 * If these form security checks are still in this place in a month or two
4552 * I'm going to simply delete them.
4555 /* This is separate for a reason. It has to be _before_ all script, etc,
4556 * AND I don't want to break anything that uses checkLinkSecurity() in
4560 if (!d
->m_submitForm
) {
4561 if (u
.protocol() != "https" && u
.protocol() != "mailto") {
4562 if (d
->m_ssl_in_use
) { // Going from SSL -> nonSSL
4563 int rc
= KMessageBox::warningContinueCancel(NULL
, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted."
4564 "\nA third party may be able to intercept and view this information."
4565 "\nAre you sure you wish to continue?"),
4566 i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
4567 if (rc
== KMessageBox::Cancel
)
4569 } else { // Going from nonSSL -> nonSSL
4570 KSSLSettings
kss(true);
4571 if (kss
.warnOnUnencrypted()) {
4572 int rc
= KMessageBox::warningContinueCancel(NULL
,
4573 i18n("Warning: Your data is about to be transmitted across the network unencrypted."
4574 "\nAre you sure you wish to continue?"),
4575 i18n("Network Transmission"),
4576 KGuiItem(i18n("&Send Unencrypted")),
4577 KStandardGuiItem::cancel(),
4578 "WarnOnUnencryptedForm");
4579 // Move this setting into KSSL instead
4580 QString grpNotifMsgs
= QLatin1String("Notification Messages");
4581 KConfigGroup
cg( KGlobal::config(), grpNotifMsgs
);
4583 if (!cg
.readEntry("WarnOnUnencryptedForm", true)) {
4584 cg
.deleteEntry("WarnOnUnencryptedForm");
4586 kss
.setWarnOnUnencrypted(false);
4589 if (rc
== KMessageBox::Cancel
)
4595 if (u
.protocol() == "mailto") {
4596 int rc
= KMessageBox::warningContinueCancel(NULL
,
4597 i18n("This site is attempting to submit form data via email.\n"
4598 "Do you want to continue?"),
4599 i18n("Network Transmission"),
4600 KGuiItem(i18n("&Send Email")),
4601 KStandardGuiItem::cancel(),
4602 "WarnTriedEmailSubmit");
4604 if (rc
== KMessageBox::Cancel
) {
4610 // End form security checks
4613 QString urlstring
= u
.url();
4615 if ( d
->isJavaScriptURL(urlstring
) ) {
4616 crossFrameExecuteScript( _target
, d
->codeForJavaScriptURL(urlstring
) );
4620 if (!checkLinkSecurity(u
,
4621 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>" ),
4625 // OK. We're actually going to submit stuff. Clear any redirections,
4626 // we should win over them
4627 d
->clearRedirection();
4629 KParts::OpenUrlArguments args
;
4631 if (!d
->m_referrer
.isEmpty())
4632 args
.metaData()["referrer"] = d
->m_referrer
;
4634 args
.metaData().insert("PropagateHttpHeader", "true");
4635 args
.metaData().insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
4636 args
.metaData().insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
4637 args
.metaData().insert("main_frame_request",
4638 parentPart() == 0 ? "TRUE":"FALSE");
4639 args
.metaData().insert("ssl_was_in_use", d
->m_ssl_in_use
? "TRUE":"FALSE");
4640 args
.metaData().insert("ssl_activate_warnings", "TRUE");
4641 //WABA: When we post a form we should treat it as the main url
4642 //the request should never be considered cross-domain
4643 //args.metaData().insert("cross-domain", toplevelURL().url());
4644 KParts::BrowserArguments browserArgs
;
4645 browserArgs
.frameName
= _target
.isEmpty() ? d
->m_doc
->baseTarget() : _target
;
4647 // Handle mailto: forms
4648 if (u
.protocol() == "mailto") {
4649 // 1) Check for attach= and strip it
4650 QString q
= u
.query().mid(1);
4651 QStringList nvps
= q
.split("&");
4652 bool triedToAttach
= false;
4654 QStringList::Iterator nvp
= nvps
.begin();
4655 const QStringList::Iterator nvpEnd
= nvps
.end();
4657 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
4658 // remove returns an iterator pointing to the next item
4660 while (nvp
!= nvpEnd
) {
4661 const QStringList pair
= (*nvp
).split("=");
4662 if (pair
.count() >= 2) {
4663 if (pair
.first().toLower() == "attach") {
4664 nvp
= nvps
.erase(nvp
);
4665 triedToAttach
= true;
4675 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");
4679 if (contentType
.toLower() == "multipart/form-data") {
4680 // FIXME: is this correct? I suspect not
4681 bodyEnc
= QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData
.data(),
4683 } else if (contentType
.toLower() == "text/plain") {
4684 // Convention seems to be to decode, and s/&/\n/
4685 QString tmpbody
= QString::fromLatin1(formData
.data(),
4687 tmpbody
.replace(QRegExp("[&]"), "\n");
4688 tmpbody
.replace(QRegExp("[+]"), " ");
4689 tmpbody
= KUrl::fromPercentEncoding(tmpbody
.toLatin1()); // Decode the rest of it
4690 bodyEnc
= QLatin1String( KUrl::toPercentEncoding(tmpbody
) ); // Recode for the URL
4692 bodyEnc
= QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData
.data(),
4693 formData
.size())) );
4696 nvps
.append(QString("body=%1").arg(bodyEnc
));
4701 if ( strcmp( action
, "get" ) == 0 ) {
4702 if (u
.protocol() != "mailto")
4703 u
.setQuery( QString::fromLatin1( formData
.data(), formData
.size() ) );
4704 browserArgs
.setDoPost( false );
4707 browserArgs
.postData
= formData
;
4708 browserArgs
.setDoPost( true );
4710 // construct some user headers if necessary
4711 if (contentType
.isNull() || contentType
== "application/x-www-form-urlencoded")
4712 browserArgs
.setContentType( "Content-Type: application/x-www-form-urlencoded" );
4713 else // contentType must be "multipart/form-data"
4714 browserArgs
.setContentType( "Content-Type: " + contentType
+ "; boundary=" + boundary
);
4717 if ( d
->m_doc
->parsing() || d
->m_runningScripts
> 0 ) {
4718 if( d
->m_submitForm
) {
4719 kDebug(6000) << "ABORTING!";
4722 d
->m_submitForm
= new KHTMLPartPrivate::SubmitForm
;
4723 d
->m_submitForm
->submitAction
= action
;
4724 d
->m_submitForm
->submitUrl
= url
;
4725 d
->m_submitForm
->submitFormData
= formData
;
4726 d
->m_submitForm
->target
= _target
;
4727 d
->m_submitForm
->submitContentType
= contentType
;
4728 d
->m_submitForm
->submitBoundary
= boundary
;
4729 connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
4733 emit d
->m_extension
->openUrlRequest( u
, args
, browserArgs
);
4737 void KHTMLPart::popupMenu( const QString
&linkUrl
)
4741 KParts::OpenUrlArguments args
;
4742 KParts::BrowserArguments browserArgs
;
4744 KParts::BrowserExtension::PopupFlags itemflags
=KParts::BrowserExtension::ShowBookmark
| KParts::BrowserExtension::ShowReload
;
4746 if ( linkUrl
.isEmpty() ) { // click on background
4747 KHTMLPart
* khtmlPart
= this;
4748 while ( khtmlPart
->parentPart() )
4750 khtmlPart
=khtmlPart
->parentPart();
4752 popupURL
= khtmlPart
->url();
4753 referrer
= khtmlPart
->pageReferrer();
4755 itemflags
= KParts::BrowserExtension::ShowTextSelectionItems
;
4757 itemflags
|= KParts::BrowserExtension::ShowNavigationItems
;
4758 } else { // click on link
4759 popupURL
= completeURL( linkUrl
);
4760 linkKUrl
= popupURL
;
4761 referrer
= this->referrer();
4762 itemflags
|= KParts::BrowserExtension::IsLink
;
4764 if (!(d
->m_strSelectedURLTarget
).isEmpty() &&
4765 (d
->m_strSelectedURLTarget
.toLower() != "_top") &&
4766 (d
->m_strSelectedURLTarget
.toLower() != "_self") &&
4767 (d
->m_strSelectedURLTarget
.toLower() != "_parent")) {
4768 if (d
->m_strSelectedURLTarget
.toLower() == "_blank")
4769 browserArgs
.setForcesNewWindow(true);
4771 KHTMLPart
*p
= this;
4772 while (p
->parentPart())
4773 p
= p
->parentPart();
4774 if (!p
->frameExists(d
->m_strSelectedURLTarget
))
4775 browserArgs
.setForcesNewWindow(true);
4780 // Danger, Will Robinson. The Popup might stay around for a much
4781 // longer time than KHTMLPart. Deal with it.
4782 KHTMLPopupGUIClient
* client
= new KHTMLPopupGUIClient( this, linkKUrl
);
4783 QPointer
<QObject
> guard( client
);
4785 QString mimetype
= QLatin1String( "text/html" );
4786 args
.metaData()["referrer"] = referrer
;
4788 if (!linkUrl
.isEmpty()) // over a link
4790 if (popupURL
.isLocalFile()) // safe to do this
4792 mimetype
= KMimeType::findByUrl(popupURL
,0,true,false)->name();
4794 else // look at "extension" of link
4796 const QString
fname(popupURL
.fileName(KUrl::ObeyTrailingSlash
));
4797 if (!fname
.isEmpty() && !popupURL
.hasRef() && popupURL
.query().isEmpty())
4799 KMimeType::Ptr pmt
= KMimeType::findByPath(fname
,0,true);
4801 // Further check for mime types guessed from the extension which,
4802 // on a web page, are more likely to be a script delivering content
4803 // of undecidable type. If the mime type from the extension is one
4804 // of these, don't use it. Retain the original type 'text/html'.
4805 if (pmt
->name() != KMimeType::defaultMimeType() &&
4806 !pmt
->is("application/x-perl") &&
4807 !pmt
->is("application/x-perl-module") &&
4808 !pmt
->is("application/x-php") &&
4809 !pmt
->is("application/x-python-bytecode") &&
4810 !pmt
->is("application/x-python") &&
4811 !pmt
->is("application/x-shellscript"))
4812 mimetype
= pmt
->name();
4817 args
.setMimeType(mimetype
);
4819 emit d
->m_extension
->popupMenu( QCursor::pos(), popupURL
, S_IFREG
/*always a file*/,
4820 args
, browserArgs
, itemflags
,
4821 client
->actionGroups() );
4823 if ( !guard
.isNull() ) {
4825 emit
popupMenu(linkUrl
, QCursor::pos());
4826 d
->m_strSelectedURL
.clear();
4827 d
->m_strSelectedURLTarget
.clear();
4831 void KHTMLPart::slotParentCompleted()
4833 //kDebug(6050) << this;
4834 if ( !d
->m_redirectURL
.isEmpty() && !d
->m_redirectionTimer
.isActive() )
4836 //kDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL;
4837 d
->m_redirectionTimer
.setSingleShot( true );
4838 d
->m_redirectionTimer
.start( qMax(0, 1000 * d
->m_delayRedirect
) );
4842 void KHTMLPart::slotChildStarted( KIO::Job
*job
)
4844 khtml::ChildFrame
*child
= frame( sender() );
4848 child
->m_bCompleted
= false;
4850 if ( d
->m_bComplete
)
4853 // WABA: Looks like this belongs somewhere else
4854 if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
4856 emit d
->m_extension
->openURLNotify();
4859 d
->m_bComplete
= false;
4860 emit
started( job
);
4864 void KHTMLPart::slotChildCompleted()
4866 slotChildCompleted( false );
4869 void KHTMLPart::slotChildCompleted( bool pendingAction
)
4871 khtml::ChildFrame
*child
= frame( sender() );
4874 kDebug(6050) << this << "child=" << child
<< "m_partContainerElement=" << child
->m_partContainerElement
;
4875 child
->m_bCompleted
= true;
4876 child
->m_bPendingRedirection
= pendingAction
;
4877 child
->m_args
= KParts::OpenUrlArguments();
4878 child
->m_browserArgs
= KParts::BrowserArguments();
4879 // dispatch load event
4880 if (!qobject_cast
<KHTMLPart
*>(child
->m_part
))
4881 QTimer::singleShot(0, child
->m_partContainerElement
, SLOT(slotEmitLoadEvent()));
4886 void KHTMLPart::slotChildDocCreated()
4888 // Set domain to the frameset's domain
4889 // This must only be done when loading the frameset initially (#22039),
4890 // not when following a link in a frame (#44162).
4891 if (KHTMLPart
* htmlFrame
= qobject_cast
<KHTMLPart
*>(sender()))
4892 d
->propagateInitialDomainTo( htmlFrame
);
4894 // So it only happens once
4895 disconnect( sender(), SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
4898 void KHTMLPartPrivate::propagateInitialDomainTo(KHTMLPart
* kid
)
4900 // This method is used to propagate our domain information for
4901 // child frames, potentially widening to have less periods, and also
4902 // to provide a domain for about: or JavaScript: URLs altogether.
4903 // Note that DocumentImpl:;setDomain does the checking.
4904 if ( m_doc
&& kid
->d
->m_doc
)
4905 kid
->d
->m_doc
->setDomain( m_doc
->domain() );
4908 void KHTMLPart::slotChildURLRequest( const KUrl
&url
, const KParts::OpenUrlArguments
& args
, const KParts::BrowserArguments
&browserArgs
)
4910 khtml::ChildFrame
*child
= frame( sender()->parent() );
4911 KHTMLPart
*callingHtmlPart
= const_cast<KHTMLPart
*>(dynamic_cast<const KHTMLPart
*>(sender()->parent()));
4913 // TODO: handle child target correctly! currently the script are always executed for the parent
4914 QString urlStr
= url
.url();
4915 if ( d
->isJavaScriptURL(urlStr
) ) {
4916 executeScript( DOM::Node(), d
->codeForJavaScriptURL(urlStr
) );
4920 QString frameName
= browserArgs
.frameName
.toLower();
4921 if ( !frameName
.isEmpty() ) {
4922 if ( frameName
== QLatin1String( "_top" ) )
4924 emit d
->m_extension
->openUrlRequest( url
, args
, browserArgs
);
4927 else if ( frameName
== QLatin1String( "_blank" ) )
4929 emit d
->m_extension
->createNewWindow( url
, args
, browserArgs
);
4932 else if ( frameName
== QLatin1String( "_parent" ) )
4934 KParts::BrowserArguments
newBrowserArgs( browserArgs
);
4935 newBrowserArgs
.frameName
.clear();
4936 emit d
->m_extension
->openUrlRequest( url
, args
, newBrowserArgs
);
4939 else if ( frameName
!= QLatin1String( "_self" ) )
4941 khtml::ChildFrame
*_frame
= recursiveFrameRequest( callingHtmlPart
, url
, args
, browserArgs
);
4945 emit d
->m_extension
->openUrlRequest( url
, args
, browserArgs
);
4953 if ( child
&& child
->m_type
!= khtml::ChildFrame::Object
) {
4954 // Inform someone that we are about to show something else.
4955 child
->m_bNotify
= true;
4956 requestObject( child
, url
, args
, browserArgs
);
4957 } else if ( frameName
== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
4959 KParts::BrowserArguments
newBrowserArgs( browserArgs
);
4960 newBrowserArgs
.frameName
.clear();
4961 emit d
->m_extension
->openUrlRequest( url
, args
, newBrowserArgs
);
4965 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart
* )
4967 emit d
->m_extension
->requestFocus(this);
4970 khtml::ChildFrame
*KHTMLPart::frame( const QObject
*obj
)
4972 assert( obj
->inherits( "KParts::ReadOnlyPart" ) );
4973 const KParts::ReadOnlyPart
* const part
= static_cast<const KParts::ReadOnlyPart
*>( obj
);
4975 FrameIt it
= d
->m_frames
.begin();
4976 const FrameIt end
= d
->m_frames
.end();
4977 for (; it
!= end
; ++it
)
4978 if ( (KParts::ReadOnlyPart
*)(*it
)->m_part
== part
)
4981 FrameIt oi
= d
->m_objects
.begin();
4982 const FrameIt oiEnd
= d
->m_objects
.end();
4983 for (; oi
!= oiEnd
; ++oi
)
4984 if ( (KParts::ReadOnlyPart
*)(*oi
)->m_part
== part
)
4990 //#define DEBUG_FINDFRAME
4992 bool KHTMLPart::checkFrameAccess(KHTMLPart
*callingHtmlPart
)
4994 if (callingHtmlPart
== this)
4995 return true; // trivial
4997 if (!xmlDocImpl()) {
4998 #ifdef DEBUG_FINDFRAME
4999 kDebug(6050) << "Empty part" << this << "URL = " << url();
5001 return false; // we are empty?
5004 // now compare the domains
5005 if (callingHtmlPart
&& callingHtmlPart
->xmlDocImpl() && xmlDocImpl()) {
5006 DOM::DOMString actDomain
= callingHtmlPart
->xmlDocImpl()->domain();
5007 DOM::DOMString destDomain
= xmlDocImpl()->domain();
5009 #ifdef DEBUG_FINDFRAME
5010 kDebug(6050) << "actDomain =" << actDomain
.string() << "destDomain =" << destDomain
.string();
5013 if (actDomain
== destDomain
)
5016 #ifdef DEBUG_FINDFRAME
5019 kDebug(6050) << "Unknown part/domain" << callingHtmlPart
<< "tries to access part" << this;
5026 KHTMLPart::findFrameParent( KParts::ReadOnlyPart
*callingPart
, const QString
&f
, khtml::ChildFrame
**childFrame
)
5028 #ifdef DEBUG_FINDFRAME
5029 kDebug(6050) << this << "URL =" << url() << "name =" << name() << "findFrameParent(" << f
<< ")";
5032 KHTMLPart
* const callingHtmlPart
= dynamic_cast<KHTMLPart
*>(callingPart
);
5034 if (!checkFrameAccess(callingHtmlPart
))
5037 if (!childFrame
&& !parentPart() && (objectName() == f
))
5040 FrameIt it
= d
->m_frames
.find( f
);
5041 const FrameIt end
= d
->m_frames
.end();
5044 #ifdef DEBUG_FINDFRAME
5045 kDebug(6050) << "FOUND!";
5052 it
= d
->m_frames
.begin();
5053 for (; it
!= end
; ++it
)
5055 KParts::ReadOnlyPart
* const p
= (*it
)->m_part
;
5056 if ( p
&& p
->inherits( "KHTMLPart" ))
5058 KHTMLPart
* const frameParent
= static_cast<KHTMLPart
*>(p
)->findFrameParent(callingPart
, f
, childFrame
);
5067 KHTMLPart
*KHTMLPart::findFrame( const QString
&f
)
5069 khtml::ChildFrame
*childFrame
;
5070 KHTMLPart
*parentFrame
= findFrameParent(this, f
, &childFrame
);
5073 KParts::ReadOnlyPart
*p
= childFrame
->m_part
;
5074 if ( p
&& p
->inherits( "KHTMLPart" ))
5075 return static_cast<KHTMLPart
*>(p
);
5080 KParts::ReadOnlyPart
*KHTMLPart::findFramePart(const QString
&f
)
5082 khtml::ChildFrame
*childFrame
;
5083 return findFrameParent(this, f
, &childFrame
) ? static_cast<KParts::ReadOnlyPart
*>(childFrame
->m_part
) : 0L;
5086 KParts::ReadOnlyPart
*KHTMLPart::currentFrame() const
5088 KParts::ReadOnlyPart
* part
= (KParts::ReadOnlyPart
*)(this);
5089 // Find active part in our frame manager, in case we are a frameset
5090 // and keep doing that (in case of nested framesets).
5091 // Just realized we could also do this recursively, calling part->currentFrame()...
5092 while ( part
&& part
->inherits("KHTMLPart") &&
5093 static_cast<KHTMLPart
*>(part
)->d
->m_frames
.count() > 0 ) {
5094 KHTMLPart
* frameset
= static_cast<KHTMLPart
*>(part
);
5095 part
= static_cast<KParts::ReadOnlyPart
*>(frameset
->partManager()->activePart());
5096 if ( !part
) return frameset
;
5101 bool KHTMLPart::frameExists( const QString
&frameName
)
5103 FrameIt it
= d
->m_frames
.find( frameName
);
5104 if ( it
== d
->m_frames
.end() )
5107 // WABA: We only return true if the child actually has a frame
5108 // set. Otherwise we might find our preloaded-selve.
5109 // This happens when we restore the frameset.
5110 return (!(*it
)->m_partContainerElement
.isNull());
5113 KJSProxy
*KHTMLPart::framejScript(KParts::ReadOnlyPart
*framePart
)
5115 KHTMLPart
* const kp
= qobject_cast
<KHTMLPart
*>(framePart
);
5117 return kp
->jScript();
5119 FrameIt it
= d
->m_frames
.begin();
5120 const FrameIt itEnd
= d
->m_frames
.end();
5122 for (; it
!= itEnd
; ++it
)
5123 if (framePart
== (*it
)->m_part
) {
5124 if (!(*it
)->m_jscript
)
5126 return (*it
)->m_jscript
;
5131 KHTMLPart
*KHTMLPart::parentPart()
5133 return qobject_cast
<KHTMLPart
*>( parent() );
5136 khtml::ChildFrame
*KHTMLPart::recursiveFrameRequest( KHTMLPart
*callingHtmlPart
, const KUrl
&url
,
5137 const KParts::OpenUrlArguments
&args
,
5138 const KParts::BrowserArguments
&browserArgs
, bool callParent
)
5140 #ifdef DEBUG_FINDFRAME
5141 kDebug( 6050 ) << this << "frame = " << args
.frameName
<< "url = " << url
;
5143 khtml::ChildFrame
*childFrame
;
5144 KHTMLPart
*childPart
= findFrameParent(callingHtmlPart
, browserArgs
.frameName
, &childFrame
);
5147 if (childPart
== this)
5150 childPart
->requestObject( childFrame
, url
, args
, browserArgs
);
5154 if ( parentPart() && callParent
)
5156 khtml::ChildFrame
*res
= parentPart()->recursiveFrameRequest( callingHtmlPart
, url
, args
, browserArgs
, callParent
);
5159 parentPart()->requestObject( res
, url
, args
, browserArgs
);
5165 #ifdef DEBUG_SAVESTATE
5166 static int s_saveStateIndentLevel
= 0;
5169 void KHTMLPart::saveState( QDataStream
&stream
)
5171 #ifdef DEBUG_SAVESTATE
5172 QString indent
= QString().leftJustified( s_saveStateIndentLevel
* 4, ' ' );
5173 const int indentLevel
= s_saveStateIndentLevel
++;
5174 kDebug( 6050 ) << indent
<< "saveState this=" << this << " '" << objectName() << "' saving URL " << url().url();
5177 stream
<< url() << (qint32
)d
->m_view
->contentsX() << (qint32
)d
->m_view
->contentsY()
5178 << (qint32
) d
->m_view
->contentsWidth() << (qint32
) d
->m_view
->contentsHeight() << (qint32
) d
->m_view
->marginWidth() << (qint32
) d
->m_view
->marginHeight();
5180 // save link cursor position
5181 int focusNodeNumber
;
5182 if (!d
->m_focusNodeRestored
)
5183 focusNodeNumber
= d
->m_focusNodeNumber
;
5184 else if (d
->m_doc
&& d
->m_doc
->focusNode())
5185 focusNodeNumber
= d
->m_doc
->nodeAbsIndex(d
->m_doc
->focusNode());
5187 focusNodeNumber
= -1;
5188 stream
<< focusNodeNumber
;
5190 // Save the doc's cache id.
5191 stream
<< d
->m_cacheId
;
5193 // Save the state of the document (Most notably the state of any forms)
5194 QStringList docState
;
5197 docState
= d
->m_doc
->docState();
5199 stream
<< d
->m_encoding
<< d
->m_sheetUsed
<< docState
;
5201 stream
<< d
->m_zoomFactor
;
5202 stream
<< d
->m_fontScaleFactor
;
5204 stream
<< d
->m_httpHeaders
;
5205 stream
<< d
->m_pageServices
;
5206 stream
<< d
->m_pageReferrer
;
5209 stream
<< d
->m_ssl_in_use
5210 << d
->m_ssl_peer_chain
5213 << d
->m_ssl_protocol_version
5214 << d
->m_ssl_cipher_used_bits
5215 << d
->m_ssl_cipher_bits
5216 << d
->m_ssl_cert_errors
5217 << d
->m_ssl_parent_ip
5218 << d
->m_ssl_parent_cert
;
5221 QStringList frameNameLst
, frameServiceTypeLst
, frameServiceNameLst
;
5222 KUrl::List frameURLLst
;
5223 QList
<QByteArray
> frameStateBufferLst
;
5224 QList
<int> frameTypeLst
;
5226 ConstFrameIt it
= d
->m_frames
.constBegin();
5227 const ConstFrameIt end
= d
->m_frames
.constEnd();
5228 for (; it
!= end
; ++it
)
5230 if ( !(*it
)->m_part
)
5233 frameNameLst
<< (*it
)->m_name
;
5234 frameServiceTypeLst
<< (*it
)->m_serviceType
;
5235 frameServiceNameLst
<< (*it
)->m_serviceName
;
5236 frameURLLst
<< (*it
)->m_part
->url();
5239 QDataStream
frameStream( &state
, QIODevice::WriteOnly
);
5241 if ( (*it
)->m_extension
)
5242 (*it
)->m_extension
->saveState( frameStream
);
5244 frameStateBufferLst
<< state
;
5246 frameTypeLst
<< int( (*it
)->m_type
);
5250 stream
<< (quint32
) frameNameLst
.count();
5251 stream
<< frameNameLst
<< frameServiceTypeLst
<< frameServiceNameLst
<< frameURLLst
<< frameStateBufferLst
<< frameTypeLst
;
5252 #ifdef DEBUG_SAVESTATE
5253 s_saveStateIndentLevel
= indentLevel
;
5257 void KHTMLPart::restoreState( QDataStream
&stream
)
5260 qint32 xOffset
, yOffset
, wContents
, hContents
, mWidth
, mHeight
;
5262 QStringList frameNames
, frameServiceTypes
, docState
, frameServiceNames
;
5263 QList
<int> frameTypes
;
5264 KUrl::List frameURLs
;
5265 QList
<QByteArray
> frameStateBuffers
;
5267 QString encoding
, sheetUsed
;
5268 long old_cacheId
= d
->m_cacheId
;
5270 stream
>> u
>> xOffset
>> yOffset
>> wContents
>> hContents
>> mWidth
>> mHeight
;
5272 d
->m_view
->setMarginWidth( mWidth
);
5273 d
->m_view
->setMarginHeight( mHeight
);
5275 // restore link cursor position
5276 // nth node is active. value is set in checkCompleted()
5277 stream
>> d
->m_focusNodeNumber
;
5278 d
->m_focusNodeRestored
= false;
5280 stream
>> d
->m_cacheId
;
5282 stream
>> encoding
>> sheetUsed
>> docState
;
5284 d
->m_encoding
= encoding
;
5285 d
->m_sheetUsed
= sheetUsed
;
5288 stream
>> zoomFactor
;
5289 setZoomFactor(zoomFactor
);
5291 int fontScaleFactor
;
5292 stream
>> fontScaleFactor
;
5293 setFontScaleFactor(fontScaleFactor
);
5295 stream
>> d
->m_httpHeaders
;
5296 stream
>> d
->m_pageServices
;
5297 stream
>> d
->m_pageReferrer
;
5300 stream
>> d
->m_ssl_in_use
5301 >> d
->m_ssl_peer_chain
5304 >> d
->m_ssl_protocol_version
5305 >> d
->m_ssl_cipher_used_bits
5306 >> d
->m_ssl_cipher_bits
5307 >> d
->m_ssl_cert_errors
5308 >> d
->m_ssl_parent_ip
5309 >> d
->m_ssl_parent_cert
;
5311 setPageSecurity( d
->m_ssl_in_use
? Encrypted
: NotCrypted
);
5313 stream
>> frameCount
>> frameNames
>> frameServiceTypes
>> frameServiceNames
5314 >> frameURLs
>> frameStateBuffers
>> frameTypes
;
5316 d
->m_bComplete
= false;
5317 d
->m_bLoadEventEmitted
= false;
5319 // kDebug( 6050 ) << "docState.count() = " << docState.count();
5320 // kDebug( 6050 ) << "m_url " << url().url() << " <-> " << u.url();
5321 // kDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount;
5323 if (d
->m_cacheId
== old_cacheId
)
5326 d
->m_redirectionTimer
.stop();
5328 FrameIt fIt
= d
->m_frames
.begin();
5329 const FrameIt fEnd
= d
->m_frames
.end();
5331 for (; fIt
!= fEnd
; ++fIt
)
5332 (*fIt
)->m_bCompleted
= false;
5334 fIt
= d
->m_frames
.begin();
5336 QStringList::ConstIterator fNameIt
= frameNames
.constBegin();
5337 QStringList::ConstIterator fServiceTypeIt
= frameServiceTypes
.constBegin();
5338 QStringList::ConstIterator fServiceNameIt
= frameServiceNames
.constBegin();
5339 KUrl::List::ConstIterator fURLIt
= frameURLs
.constBegin();
5340 QList
<QByteArray
>::ConstIterator fBufferIt
= frameStateBuffers
.constBegin();
5341 QList
<int>::ConstIterator fFrameTypeIt
= frameTypes
.constBegin();
5343 for (; fIt
!= fEnd
; ++fIt
, ++fNameIt
, ++fServiceTypeIt
, ++fServiceNameIt
, ++fURLIt
, ++fBufferIt
, ++fFrameTypeIt
)
5345 khtml::ChildFrame
* const child
= *fIt
;
5347 // kDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt;
5349 if ( child
->m_name
!= *fNameIt
|| child
->m_serviceType
!= *fServiceTypeIt
)
5351 child
->m_bPreloaded
= true;
5352 child
->m_name
= *fNameIt
;
5353 child
->m_serviceName
= *fServiceNameIt
;
5354 child
->m_type
= static_cast<khtml::ChildFrame::Type
>(*fFrameTypeIt
);
5355 processObjectRequest( child
, *fURLIt
, *fServiceTypeIt
);
5357 if ( child
->m_part
)
5359 child
->m_bCompleted
= false;
5360 if ( child
->m_extension
&& !(*fBufferIt
).isEmpty() )
5362 QDataStream
frameStream( *fBufferIt
);
5363 child
->m_extension
->restoreState( frameStream
);
5366 child
->m_part
->openUrl( *fURLIt
);
5370 KParts::OpenUrlArguments
args( arguments() );
5371 args
.setXOffset(xOffset
);
5372 args
.setYOffset(yOffset
);
5375 KParts::BrowserArguments
browserArgs( d
->m_extension
->browserArguments() );
5376 browserArgs
.docState
= docState
;
5377 d
->m_extension
->setBrowserArguments(browserArgs
);
5379 d
->m_view
->resizeContents( wContents
, hContents
);
5380 d
->m_view
->setContentsPos( xOffset
, yOffset
);
5388 // We must force a clear because we want to be sure to delete all
5390 d
->m_bCleared
= false;
5392 d
->m_encoding
= encoding
;
5393 d
->m_sheetUsed
= sheetUsed
;
5395 QStringList::ConstIterator fNameIt
= frameNames
.constBegin();
5396 const QStringList::ConstIterator fNameEnd
= frameNames
.constEnd();
5398 QStringList::ConstIterator fServiceTypeIt
= frameServiceTypes
.constBegin();
5399 QStringList::ConstIterator fServiceNameIt
= frameServiceNames
.constBegin();
5400 KUrl::List::ConstIterator fURLIt
= frameURLs
.constBegin();
5401 QList
<QByteArray
>::ConstIterator fBufferIt
= frameStateBuffers
.constBegin();
5402 QList
<int>::ConstIterator fFrameTypeIt
= frameTypes
.constBegin();
5404 for (; fNameIt
!= fNameEnd
; ++fNameIt
, ++fServiceTypeIt
, ++fServiceNameIt
, ++fURLIt
, ++fBufferIt
, ++fFrameTypeIt
)
5406 khtml::ChildFrame
* const newChild
= new khtml::ChildFrame
;
5407 newChild
->m_bPreloaded
= true;
5408 newChild
->m_name
= *fNameIt
;
5409 newChild
->m_serviceName
= *fServiceNameIt
;
5410 newChild
->m_type
= static_cast<khtml::ChildFrame::Type
>(*fFrameTypeIt
);
5412 // kDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt;
5414 const FrameIt childFrame
= d
->m_frames
.insert( d
->m_frames
.end(), newChild
);
5416 processObjectRequest( *childFrame
, *fURLIt
, *fServiceTypeIt
);
5418 (*childFrame
)->m_bPreloaded
= true;
5420 if ( (*childFrame
)->m_part
)
5422 if ( (*childFrame
)->m_extension
&& !(*fBufferIt
).isEmpty() )
5424 QDataStream
frameStream( *fBufferIt
);
5425 (*childFrame
)->m_extension
->restoreState( frameStream
);
5428 (*childFrame
)->m_part
->openUrl( *fURLIt
);
5432 KParts::OpenUrlArguments
args( arguments() );
5433 args
.setXOffset(xOffset
);
5434 args
.setYOffset(yOffset
);
5437 KParts::BrowserArguments
browserArgs( d
->m_extension
->browserArguments() );
5438 browserArgs
.docState
= docState
;
5439 d
->m_extension
->setBrowserArguments(browserArgs
);
5441 if (!KHTMLPageCache::self()->isComplete(d
->m_cacheId
))
5443 d
->m_restored
= true;
5445 d
->m_restored
= false;
5455 void KHTMLPart::show()
5461 void KHTMLPart::hide()
5467 DOM::Node
KHTMLPart::nodeUnderMouse() const
5469 return d
->m_view
->nodeUnderMouse();
5472 DOM::Node
KHTMLPart::nonSharedNodeUnderMouse() const
5474 return d
->m_view
->nonSharedNodeUnderMouse();
5477 void KHTMLPart::emitSelectionChanged()
5479 emit d
->m_extension
->enableAction( "copy", hasSelection() );
5481 emit d
->m_extension
->selectionInfo( selectedText() );
5482 emit
selectionChanged();
5485 int KHTMLPart::zoomFactor() const
5487 return d
->m_zoomFactor
;
5490 // ### make the list configurable ?
5491 static const int zoomSizes
[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
5492 static const int zoomSizeCount
= (sizeof(zoomSizes
) / sizeof(int));
5493 static const int minZoom
= 20;
5494 static const int maxZoom
= 300;
5496 // My idea of useful stepping ;-) (LS)
5497 extern const int KDE_NO_EXPORT fastZoomSizes
[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
5498 extern const int KDE_NO_EXPORT fastZoomSizeCount
= sizeof fastZoomSizes
/ sizeof fastZoomSizes
[0];
5500 void KHTMLPart::slotIncZoom()
5502 zoomIn(zoomSizes
, zoomSizeCount
);
5505 void KHTMLPart::slotDecZoom()
5507 zoomOut(zoomSizes
, zoomSizeCount
);
5510 void KHTMLPart::slotIncZoomFast()
5512 zoomIn(fastZoomSizes
, fastZoomSizeCount
);
5515 void KHTMLPart::slotDecZoomFast()
5517 zoomOut(fastZoomSizes
, fastZoomSizeCount
);
5520 void KHTMLPart::zoomIn(const int stepping
[], int count
)
5522 int zoomFactor
= d
->m_zoomFactor
;
5524 if (zoomFactor
< maxZoom
) {
5525 // find the entry nearest to the given zoomsizes
5526 for (int i
= 0; i
< count
; ++i
)
5527 if (stepping
[i
] > zoomFactor
) {
5528 zoomFactor
= stepping
[i
];
5531 setZoomFactor(zoomFactor
);
5535 void KHTMLPart::zoomOut(const int stepping
[], int count
)
5537 int zoomFactor
= d
->m_zoomFactor
;
5538 if (zoomFactor
> minZoom
) {
5539 // find the entry nearest to the given zoomsizes
5540 for (int i
= count
-1; i
>= 0; --i
)
5541 if (stepping
[i
] < zoomFactor
) {
5542 zoomFactor
= stepping
[i
];
5545 setZoomFactor(zoomFactor
);
5549 void KHTMLPart::setZoomFactor (int percent
)
5551 // ### zooming under 100% is majorly botched,
5552 // so disable that for now.
5553 if (percent
< 100) percent
= 100;
5554 // ### if (percent < minZoom) percent = minZoom;
5556 if (percent
> maxZoom
) percent
= maxZoom
;
5557 if (d
->m_zoomFactor
== percent
) return;
5558 d
->m_zoomFactor
= percent
;
5561 QApplication::setOverrideCursor( Qt::WaitCursor
);
5562 d
->m_view
->setZoomLevel( d
->m_zoomFactor
);
5563 QApplication::restoreOverrideCursor();
5566 ConstFrameIt it
= d
->m_frames
.constBegin();
5567 const ConstFrameIt end
= d
->m_frames
.constEnd();
5568 for (; it
!= end
; ++it
)
5569 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
5570 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
5571 static_cast<KHTMLPart
*>( p
)->setZoomFactor(d
->m_zoomFactor
);
5574 if ( d
->m_guiProfile
== BrowserViewGUI
) {
5575 d
->m_paDecZoomFactor
->setEnabled( d
->m_zoomFactor
> minZoom
);
5576 d
->m_paIncZoomFactor
->setEnabled( d
->m_zoomFactor
< maxZoom
);
5579 void KHTMLPart::slotIncFontSize()
5581 incFontSize(zoomSizes
, zoomSizeCount
);
5584 void KHTMLPart::slotDecFontSize()
5586 decFontSize(zoomSizes
, zoomSizeCount
);
5589 void KHTMLPart::slotIncFontSizeFast()
5591 incFontSize(fastZoomSizes
, fastZoomSizeCount
);
5594 void KHTMLPart::slotDecFontSizeFast()
5596 decFontSize(fastZoomSizes
, fastZoomSizeCount
);
5599 void KHTMLPart::incFontSize(const int stepping
[], int count
)
5601 int zoomFactor
= d
->m_fontScaleFactor
;
5603 if (zoomFactor
< maxZoom
) {
5604 // find the entry nearest to the given zoomsizes
5605 for (int i
= 0; i
< count
; ++i
)
5606 if (stepping
[i
] > zoomFactor
) {
5607 zoomFactor
= stepping
[i
];
5610 setFontScaleFactor(zoomFactor
);
5614 void KHTMLPart::decFontSize(const int stepping
[], int count
)
5616 int zoomFactor
= d
->m_fontScaleFactor
;
5617 if (zoomFactor
> minZoom
) {
5618 // find the entry nearest to the given zoomsizes
5619 for (int i
= count
-1; i
>= 0; --i
)
5620 if (stepping
[i
] < zoomFactor
) {
5621 zoomFactor
= stepping
[i
];
5624 setFontScaleFactor(zoomFactor
);
5628 void KHTMLPart::setFontScaleFactor(int percent
)
5630 if (percent
< minZoom
) percent
= minZoom
;
5631 if (percent
> maxZoom
) percent
= maxZoom
;
5632 if (d
->m_fontScaleFactor
== percent
) return;
5633 d
->m_fontScaleFactor
= percent
;
5635 if (d
->m_view
&& d
->m_doc
) {
5636 QApplication::setOverrideCursor( Qt::WaitCursor
);
5637 if (d
->m_doc
->styleSelector())
5638 d
->m_doc
->styleSelector()->computeFontSizes(d
->m_doc
->logicalDpiY(), d
->m_fontScaleFactor
);
5639 d
->m_doc
->recalcStyle( NodeImpl::Force
);
5640 QApplication::restoreOverrideCursor();
5643 ConstFrameIt it
= d
->m_frames
.constBegin();
5644 const ConstFrameIt end
= d
->m_frames
.constEnd();
5645 for (; it
!= end
; ++it
)
5646 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
5647 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
5648 static_cast<KHTMLPart
*>( p
)->setFontScaleFactor(d
->m_fontScaleFactor
);
5652 int KHTMLPart::fontScaleFactor() const
5654 return d
->m_fontScaleFactor
;
5657 void KHTMLPart::slotZoomView( int delta
)
5665 void KHTMLPart::setStatusBarText( const QString
& text
, StatusBarPriority p
)
5667 if (!d
->m_statusMessagesEnabled
)
5670 d
->m_statusBarText
[p
] = text
;
5673 QString tobe
= d
->m_statusBarText
[BarHoverText
];
5675 tobe
= d
->m_statusBarText
[BarOverrideText
];
5676 if (tobe
.isEmpty()) {
5677 tobe
= d
->m_statusBarText
[BarDefaultText
];
5678 if (!tobe
.isEmpty() && d
->m_jobspeed
)
5681 tobe
+= i18n( "(%1/s)" , KIO::convertSize( d
->m_jobspeed
) );
5685 emit
ReadOnlyPart::setStatusBarText(tobe
);
5689 void KHTMLPart::setJSStatusBarText( const QString
&text
)
5691 setStatusBarText(text
, BarOverrideText
);
5694 void KHTMLPart::setJSDefaultStatusBarText( const QString
&text
)
5696 setStatusBarText(text
, BarDefaultText
);
5699 QString
KHTMLPart::jsStatusBarText() const
5701 return d
->m_statusBarText
[BarOverrideText
];
5704 QString
KHTMLPart::jsDefaultStatusBarText() const
5706 return d
->m_statusBarText
[BarDefaultText
];
5709 QString
KHTMLPart::referrer() const
5711 return d
->m_referrer
;
5714 QString
KHTMLPart::pageReferrer() const
5716 KUrl referrerURL
= KUrl( d
->m_pageReferrer
);
5717 if (referrerURL
.isValid())
5719 QString protocol
= referrerURL
.protocol();
5721 if ((protocol
== "http") ||
5722 ((protocol
== "https") && (url().protocol() == "https")))
5724 referrerURL
.setRef(QString());
5725 referrerURL
.setUser(QString());
5726 referrerURL
.setPass(QString());
5727 return referrerURL
.url();
5735 QString
KHTMLPart::lastModified() const
5737 if ( d
->m_lastModified
.isEmpty() && url().isLocalFile() ) {
5738 // Local file: set last-modified from the file's mtime.
5739 // Done on demand to save time when this isn't needed - but can lead
5740 // to slightly wrong results if updating the file on disk w/o reloading.
5741 QDateTime lastModif
= QFileInfo( url().path() ).lastModified();
5742 d
->m_lastModified
= lastModif
.toString( Qt::LocalDate
);
5744 //kDebug(6050) << d->m_lastModified;
5745 return d
->m_lastModified
;
5748 void KHTMLPart::slotLoadImages()
5751 d
->m_doc
->docLoader()->setAutoloadImages( !d
->m_doc
->docLoader()->autoloadImages() );
5753 ConstFrameIt it
= d
->m_frames
.constBegin();
5754 const ConstFrameIt end
= d
->m_frames
.constEnd();
5755 for (; it
!= end
; ++it
)
5756 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
5757 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
5758 static_cast<KHTMLPart
*>( p
)->slotLoadImages();
5762 void KHTMLPart::reparseConfiguration()
5764 KHTMLSettings
*settings
= KHTMLGlobal::defaultHTMLSettings();
5767 setAutoloadImages( settings
->autoLoadImages() );
5769 d
->m_doc
->docLoader()->setShowAnimations( settings
->showAnimations() );
5771 d
->m_bOpenMiddleClick
= settings
->isOpenMiddleClickEnabled();
5772 d
->m_bBackRightClick
= settings
->isBackRightClickEnabled();
5773 d
->m_bJScriptEnabled
= settings
->isJavaScriptEnabled(url().host());
5774 setDebugScript( settings
->isJavaScriptDebugEnabled() );
5775 d
->m_bJavaEnabled
= settings
->isJavaEnabled(url().host());
5776 d
->m_bPluginsEnabled
= settings
->isPluginsEnabled(url().host());
5777 d
->m_metaRefreshEnabled
= settings
->isAutoDelayedActionsEnabled ();
5779 delete d
->m_settings
;
5780 d
->m_settings
= new KHTMLSettings(*KHTMLGlobal::defaultHTMLSettings());
5782 QApplication::setOverrideCursor( Qt::WaitCursor
);
5783 khtml::CSSStyleSelector::reparseConfiguration();
5784 if(d
->m_doc
) d
->m_doc
->updateStyleSelector();
5785 QApplication::restoreOverrideCursor();
5788 KHTMLSettings::KSmoothScrollingMode ssm
= d
->m_settings
->smoothScrolling();
5789 if (ssm
== KHTMLSettings::KSmoothScrollingDisabled
)
5790 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled
);
5791 else if (ssm
== KHTMLSettings::KSmoothScrollingWhenEfficient
)
5792 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient
);
5794 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled
);
5797 if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled())
5801 QStringList
KHTMLPart::frameNames() const
5805 ConstFrameIt it
= d
->m_frames
.constBegin();
5806 const ConstFrameIt end
= d
->m_frames
.constEnd();
5807 for (; it
!= end
; ++it
)
5808 if (!(*it
)->m_bPreloaded
&& (*it
)->m_part
)
5809 res
+= (*it
)->m_name
;
5814 QList
<KParts::ReadOnlyPart
*> KHTMLPart::frames() const
5816 QList
<KParts::ReadOnlyPart
*> res
;
5818 ConstFrameIt it
= d
->m_frames
.constBegin();
5819 const ConstFrameIt end
= d
->m_frames
.constEnd();
5820 for (; it
!= end
; ++it
)
5821 if (!(*it
)->m_bPreloaded
&& (*it
)->m_part
) // ### TODO: make sure that we always create an empty
5822 // KHTMLPart for frames so this never happens.
5823 res
.append( (*it
)->m_part
);
5828 bool KHTMLPart::openUrlInFrame( const KUrl
&url
, const KParts::OpenUrlArguments
& args
, const KParts::BrowserArguments
&browserArgs
)
5830 kDebug( 6050 ) << this << url
;
5831 FrameIt it
= d
->m_frames
.find( browserArgs
.frameName
);
5833 if ( it
== d
->m_frames
.end() )
5836 // Inform someone that we are about to show something else.
5837 if ( !browserArgs
.lockHistory() )
5838 emit d
->m_extension
->openUrlNotify();
5840 requestObject( *it
, url
, args
, browserArgs
);
5845 void KHTMLPart::setDNDEnabled( bool b
)
5850 bool KHTMLPart::dndEnabled() const
5855 void KHTMLPart::customEvent( QEvent
*event
)
5857 if ( khtml::MousePressEvent::test( event
) )
5859 khtmlMousePressEvent( static_cast<khtml::MousePressEvent
*>( event
) );
5863 if ( khtml::MouseDoubleClickEvent::test( event
) )
5865 khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent
*>( event
) );
5869 if ( khtml::MouseMoveEvent::test( event
) )
5871 khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent
*>( event
) );
5875 if ( khtml::MouseReleaseEvent::test( event
) )
5877 khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent
*>( event
) );
5881 if ( khtml::DrawContentsEvent::test( event
) )
5883 khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent
*>( event
) );
5887 KParts::ReadOnlyPart::customEvent( event
);
5890 bool KHTMLPart::isPointInsideSelection(int x
, int y
)
5892 // Treat a collapsed selection like no selection.
5893 if (d
->editor_context
.m_selection
.state() == Selection::CARET
)
5895 if (!xmlDocImpl()->renderer())
5898 khtml::RenderObject::NodeInfo
nodeInfo(true, true);
5899 xmlDocImpl()->renderer()->layer()->nodeAtPoint(nodeInfo
, x
, y
);
5900 NodeImpl
*innerNode
= nodeInfo
.innerNode();
5901 if (!innerNode
|| !innerNode
->renderer())
5904 return innerNode
->isPointInsideSelection(x
, y
, d
->editor_context
.m_selection
);
5907 /** returns the position of the first inline text box of the line at
5908 * coordinate y in renderNode
5910 * This is a helper function for line-by-line text selection.
5912 static bool firstRunAt(khtml::RenderObject
*renderNode
, int y
, NodeImpl
*&startNode
, long &startOffset
)
5914 for (khtml::RenderObject
*n
= renderNode
; n
; n
= n
->nextSibling()) {
5916 khtml::RenderText
* const textRenderer
= static_cast<khtml::RenderText
*>(n
);
5917 for (khtml::InlineTextBox
* box
= textRenderer
->firstTextBox(); box
; box
= box
->nextTextBox()) {
5918 if (box
->m_y
== y
&& textRenderer
->element()) {
5919 startNode
= textRenderer
->element();
5920 startOffset
= box
->m_start
;
5926 if (firstRunAt(n
->firstChild(), y
, startNode
, startOffset
)) {
5934 /** returns the position of the last inline text box of the line at
5935 * coordinate y in renderNode
5937 * This is a helper function for line-by-line text selection.
5939 static bool lastRunAt(khtml::RenderObject
*renderNode
, int y
, NodeImpl
*&endNode
, long &endOffset
)
5941 khtml::RenderObject
*n
= renderNode
;
5945 khtml::RenderObject
*next
;
5946 while ((next
= n
->nextSibling())) {
5951 if (lastRunAt(n
->firstChild(), y
, endNode
, endOffset
)) {
5956 khtml::RenderText
* const textRenderer
= static_cast<khtml::RenderText
*>(n
);
5957 for (khtml::InlineTextBox
* box
= textRenderer
->firstTextBox(); box
; box
= box
->nextTextBox()) {
5958 if (box
->m_y
== y
&& textRenderer
->element()) {
5959 endNode
= textRenderer
->element();
5960 endOffset
= box
->m_start
+ box
->m_len
;
5966 if (n
== renderNode
) {
5970 n
= n
->previousSibling();
5974 void KHTMLPart::handleMousePressEventDoubleClick(khtml::MouseDoubleClickEvent
*event
)
5976 QMouseEvent
*mouse
= event
->qmouseEvent();
5977 DOM::Node innerNode
= event
->innerNode();
5979 Selection selection
;
5981 if (mouse
->button() == Qt::LeftButton
&& !innerNode
.isNull() && innerNode
.handle()->renderer() &&
5982 innerNode
.handle()->renderer()->shouldSelect()) {
5983 Position
pos(innerNode
.handle()->positionForCoordinates(event
->x(), event
->y()));
5984 if (pos
.node() && (pos
.node()->nodeType() == Node::TEXT_NODE
|| pos
.node()->nodeType() == Node::CDATA_SECTION_NODE
)) {
5985 selection
.moveTo(pos
);
5986 selection
.expandUsingGranularity(Selection::WORD
);
5990 if (selection
.state() != Selection::CARET
) {
5991 d
->editor_context
.beginSelectingText(Selection::WORD
);
5994 setCaret(selection
);
5998 void KHTMLPart::handleMousePressEventTripleClick(khtml::MouseDoubleClickEvent
*event
)
6000 QMouseEvent
*mouse
= event
->qmouseEvent();
6001 DOM::Node innerNode
= event
->innerNode();
6003 Selection selection
;
6005 if (mouse
->button() == Qt::LeftButton
&& !innerNode
.isNull() && innerNode
.handle()->renderer() &&
6006 innerNode
.handle()->renderer()->shouldSelect()) {
6007 Position
pos(innerNode
.handle()->positionForCoordinates(event
->x(), event
->y()));
6008 if (pos
.node() && (pos
.node()->nodeType() == Node::TEXT_NODE
|| pos
.node()->nodeType() == Node::CDATA_SECTION_NODE
)) {
6009 selection
.moveTo(pos
);
6010 selection
.expandUsingGranularity(Selection::LINE
);
6014 if (selection
.state() != Selection::CARET
) {
6015 d
->editor_context
.beginSelectingText(Selection::LINE
);
6018 setCaret(selection
);
6022 void KHTMLPart::handleMousePressEventSingleClick(khtml::MousePressEvent
*event
)
6024 QMouseEvent
*mouse
= event
->qmouseEvent();
6025 DOM::Node innerNode
= event
->innerNode();
6027 if (mouse
->button() == Qt::LeftButton
) {
6030 if (!innerNode
.isNull() && innerNode
.handle()->renderer() &&
6031 innerNode
.handle()->renderer()->shouldSelect()) {
6032 bool extendSelection
= mouse
->modifiers() & Qt::ShiftModifier
;
6034 // Don't restart the selection when the mouse is pressed on an
6035 // existing selection so we can allow for text dragging.
6036 if (!extendSelection
&& isPointInsideSelection(event
->x(), event
->y())) {
6039 Position
pos(innerNode
.handle()->positionForCoordinates(event
->x(), event
->y()));
6041 pos
= Position(innerNode
.handle(), innerNode
.handle()->caretMinOffset());
6044 if (extendSelection
&& sel
.notEmpty()) {
6045 sel
.clearModifyBias();
6047 if (d
->editor_context
.m_selectionGranularity
!= Selection::CHARACTER
) {
6048 sel
.expandUsingGranularity(d
->editor_context
.m_selectionGranularity
);
6050 d
->editor_context
.m_beganSelectingText
= true;
6053 d
->editor_context
.m_selectionGranularity
= Selection::CHARACTER
;
6062 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent
*event
)
6064 DOM::DOMString url
= event
->url();
6065 QMouseEvent
*_mouse
= event
->qmouseEvent();
6066 DOM::Node innerNode
= event
->innerNode();
6067 d
->m_mousePressNode
= innerNode
;
6069 d
->m_dragStartPos
= QPoint(event
->x(), event
->y());
6071 if ( !event
->url().isNull() ) {
6072 d
->m_strSelectedURL
= event
->url().string();
6073 d
->m_strSelectedURLTarget
= event
->target().string();
6076 d
->m_strSelectedURL
.clear();
6077 d
->m_strSelectedURLTarget
.clear();
6080 if ( _mouse
->button() == Qt::LeftButton
||
6081 _mouse
->button() == Qt::MidButton
)
6083 d
->m_bMousePressed
= true;
6085 #ifdef KHTML_NO_SELECTION
6086 d
->m_dragLastPos
= _mouse
->globalPos();
6088 if ( _mouse
->button() == Qt::LeftButton
)
6090 if ( (!d
->m_strSelectedURL
.isNull() && !isEditable())
6091 || (!d
->m_mousePressNode
.isNull() && d
->m_mousePressNode
.elementId() == ID_IMG
) )
6094 d
->editor_context
.m_beganSelectingText
= false;
6096 handleMousePressEventSingleClick(event
);
6101 if ( _mouse
->button() == Qt::RightButton
&& parentPart() != 0 && d
->m_bBackRightClick
)
6103 d
->m_bRightMousePressed
= true;
6104 } else if ( _mouse
->button() == Qt::RightButton
)
6106 popupMenu( d
->m_strSelectedURL
);
6107 // might be deleted, don't touch "this"
6111 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent
*event
)
6113 QMouseEvent
*_mouse
= event
->qmouseEvent();
6114 if ( _mouse
->button() == Qt::LeftButton
)
6116 d
->m_bMousePressed
= true;
6117 d
->editor_context
.m_beganSelectingText
= false;
6119 if (event
->clickCount() == 2) {
6120 handleMousePressEventDoubleClick(event
);
6124 if (event
->clickCount() >= 3) {
6125 handleMousePressEventTripleClick(event
);
6131 #ifndef KHTML_NO_SELECTION
6132 bool KHTMLPart::isExtendingSelection() const
6134 // This is it, the whole detection. khtmlMousePressEvent only sets this
6135 // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
6136 // it's sufficient to only rely on this flag to detect selection extension.
6137 return d
->editor_context
.m_beganSelectingText
;
6140 void KHTMLPart::extendSelectionTo(int x
, int y
, const DOM::Node
&innerNode
)
6142 // handle making selection
6143 Position
pos(innerNode
.handle()->positionForCoordinates(x
, y
));
6145 // Don't modify the selection if we're not on a node.
6149 // Restart the selection if this is the first mouse move. This work is usually
6150 // done in khtmlMousePressEvent, but not if the mouse press was on an existing selection.
6151 Selection sel
= caret();
6152 sel
.clearModifyBias();
6153 if (!d
->editor_context
.m_beganSelectingText
) {
6154 // We are beginning a selection during press-drag, when the original click
6155 // wasn't appropriate for one. Make sure to set the granularity.
6156 d
->editor_context
.beginSelectingText(Selection::CHARACTER
);
6161 if (d
->editor_context
.m_selectionGranularity
!= Selection::CHARACTER
) {
6162 sel
.expandUsingGranularity(d
->editor_context
.m_selectionGranularity
);
6167 #endif // KHTML_NO_SELECTION
6169 bool KHTMLPart::handleMouseMoveEventDrag(khtml::MouseMoveEvent
*event
)
6171 #ifdef QT_NO_DRAGANDDROP
6174 DOM::Node innerNode
= event
->innerNode();
6176 if( (d
->m_bMousePressed
&&
6177 ( (!d
->m_strSelectedURL
.isEmpty() && !isEditable())
6178 || (!d
->m_mousePressNode
.isNull() && d
->m_mousePressNode
.elementId() == ID_IMG
) ) )
6179 && ( d
->m_dragStartPos
- QPoint(event
->x(), event
->y()) ).manhattanLength() > KGlobalSettings::dndEventDelay() ) {
6181 DOM::DOMString url
= event
->url();
6184 HTMLImageElementImpl
*img
= 0L;
6187 // qDebug("****************** Event URL: %s", url.string().toLatin1().constData());
6188 // qDebug("****************** Event Target: %s", target.string().toLatin1().constData());
6191 if ( url
.length() == 0 && innerNode
.handle() && innerNode
.handle()->id() == ID_IMG
)
6193 img
= static_cast<HTMLImageElementImpl
*>(innerNode
.handle());
6194 u
= KUrl( completeURL( khtml::parseURL(img
->getAttribute(ATTR_SRC
)).string() ) );
6195 pix
= KIconLoader::global()->loadIcon("image-x-generic", KIconLoader::Desktop
);
6199 // Text or image link...
6200 u
= completeURL( d
->m_strSelectedURL
);
6201 pix
= KIO::pixmapForUrl(u
, 0, KIconLoader::Desktop
, KIconLoader::SizeMedium
);
6204 u
.setPass(QString());
6206 QDrag
*drag
= new QDrag( d
->m_view
->viewport() );
6207 QMap
<QString
, QString
> metaDataMap
;
6208 if ( !d
->m_referrer
.isEmpty() )
6209 metaDataMap
.insert( "referrer", d
->m_referrer
);
6210 QMimeData
* mimeData
= new QMimeData();
6211 u
.populateMimeData( mimeData
, metaDataMap
);
6212 drag
->setMimeData( mimeData
);
6214 if( img
&& img
->complete() )
6215 drag
->mimeData()->setImageData( img
->currentImage() );
6217 if ( !pix
.isNull() )
6218 drag
->setPixmap( pix
);
6223 // when we finish our drag, we need to undo our mouse press
6224 d
->m_bMousePressed
= false;
6225 d
->m_strSelectedURL
.clear();
6226 d
->m_strSelectedURLTarget
.clear();
6230 #endif // QT_NO_DRAGANDDROP
6233 bool KHTMLPart::handleMouseMoveEventOver(khtml::MouseMoveEvent
*event
)
6235 // Mouse clicked -> do nothing
6236 if ( d
->m_bMousePressed
) return false;
6238 DOM::DOMString url
= event
->url();
6240 // The mouse is over something
6243 DOM::DOMString target
= event
->target();
6244 QMouseEvent
*_mouse
= event
->qmouseEvent();
6245 DOM::Node innerNode
= event
->innerNode();
6247 bool shiftPressed
= ( _mouse
->modifiers() & Qt::ShiftModifier
);
6250 if ( !innerNode
.isNull() && innerNode
.elementId() == ID_IMG
)
6252 HTMLImageElementImpl
*i
= static_cast<HTMLImageElementImpl
*>(innerNode
.handle());
6253 if ( i
&& i
->isServerMap() )
6255 khtml::RenderObject
*r
= i
->renderer();
6259 r
->absolutePosition(absx
, absy
);
6260 int x(event
->x() - absx
), y(event
->y() - absy
);
6262 d
->m_overURL
= url
.string() + QString("?%1,%2").arg(x
).arg(y
);
6263 d
->m_overURLTarget
= target
.string();
6264 overURL( d
->m_overURL
, target
.string(), shiftPressed
);
6271 if ( d
->m_overURL
.isEmpty() || d
->m_overURL
!= url
|| d
->m_overURLTarget
!= target
)
6273 d
->m_overURL
= url
.string();
6274 d
->m_overURLTarget
= target
.string();
6275 overURL( d
->m_overURL
, target
.string(), shiftPressed
);
6278 else // Not over a link...
6280 if( !d
->m_overURL
.isEmpty() ) // and we were over a link -> reset to "default statusbar text"
6282 // reset to "default statusbar text"
6289 void KHTMLPart::handleMouseMoveEventSelection(khtml::MouseMoveEvent
*event
)
6291 // Mouse not pressed. Do nothing.
6292 if (!d
->m_bMousePressed
)
6295 #ifdef KHTML_NO_SELECTION
6296 if (d
->m_doc
&& d
->m_view
) {
6297 QPoint
diff( mouse
->globalPos() - d
->m_dragLastPos
);
6299 if (abs(diff
.x()) > 64 || abs(diff
.y()) > 64) {
6300 d
->m_view
->scrollBy(-diff
.x(), -diff
.y());
6301 d
->m_dragLastPos
= mouse
->globalPos();
6306 QMouseEvent
*mouse
= event
->qmouseEvent();
6307 DOM::Node innerNode
= event
->innerNode();
6309 if ( (mouse
->buttons() & Qt::LeftButton
) == 0 || !innerNode
.handle() || !innerNode
.handle()->renderer() ||
6310 !innerNode
.handle()->renderer()->shouldSelect())
6313 // handle making selection
6314 extendSelectionTo(event
->x(), event
->y(), innerNode
);
6315 #endif // KHTML_NO_SELECTION
6318 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent
*event
)
6320 if (handleMouseMoveEventDrag(event
))
6323 if (handleMouseMoveEventOver(event
))
6326 handleMouseMoveEventSelection(event
);
6329 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent
*event
)
6331 DOM::Node innerNode
= event
->innerNode();
6332 d
->m_mousePressNode
= DOM::Node();
6334 if ( d
->m_bMousePressed
) {
6335 setStatusBarText(QString(), BarHoverText
);
6339 // Used to prevent mouseMoveEvent from initiating a drag before
6340 // the mouse is pressed again.
6341 d
->m_bMousePressed
= false;
6343 QMouseEvent
*_mouse
= event
->qmouseEvent();
6344 if ( _mouse
->button() == Qt::RightButton
&& parentPart() != 0 && d
->m_bBackRightClick
)
6346 d
->m_bRightMousePressed
= false;
6347 KParts::BrowserInterface
*tmp_iface
= d
->m_extension
->browserInterface();
6349 tmp_iface
->callMethod( "goHistory", -1 );
6352 #ifndef QT_NO_CLIPBOARD
6353 if ((d
->m_guiProfile
== BrowserViewGUI
) && (_mouse
->button() == Qt::MidButton
) && (event
->url().isNull())) {
6354 kDebug( 6050 ) << "MMB shouldOpen=" << d
->m_bOpenMiddleClick
;
6356 if (d
->m_bOpenMiddleClick
) {
6357 KHTMLPart
*p
= this;
6358 while (p
->parentPart()) p
= p
->parentPart();
6359 p
->d
->m_extension
->pasteRequest();
6364 #ifndef KHTML_NO_SELECTION
6367 // Clear the selection if the mouse didn't move after the last mouse press.
6368 // We do this so when clicking on the selection, the selection goes away.
6369 // However, if we are editing, place the caret.
6370 if (!d
->editor_context
.m_beganSelectingText
6371 && d
->m_dragStartPos
.x() == event
->x()
6372 && d
->m_dragStartPos
.y() == event
->y()
6373 && d
->editor_context
.m_selection
.state() == Selection::RANGE
) {
6374 Selection selection
;
6375 #ifdef APPLE_CHANGES
6376 if (d
->editor_context
.m_selection
.base().node()->isContentEditable())
6378 selection
.moveTo(d
->editor_context
.m_selection
.base().node()->positionForCoordinates(event
->x(), event
->y()));
6379 setCaret(selection
);
6381 // get selected text and paste to the clipboard
6382 #ifndef QT_NO_CLIPBOARD
6383 QString text
= selectedText();
6384 text
.replace(QChar(0xa0), ' ');
6385 if (!text
.isEmpty()) {
6386 disconnect( qApp
->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
6387 qApp
->clipboard()->setText(text
,QClipboard::Selection
);
6388 connect( qApp
->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
6391 //kDebug( 6000 ) << "selectedText = " << text;
6392 emitSelectionChanged();
6393 //kDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset();
6398 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent
* )
6402 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent
*event
)
6404 if ( event
->activated() )
6406 emitSelectionChanged();
6407 emit d
->m_extension
->enableAction( "print", d
->m_doc
!= 0 );
6409 if ( !d
->m_settings
->autoLoadImages() && d
->m_paLoadImages
)
6411 QList
<QAction
*> lst
;
6412 lst
.append( d
->m_paLoadImages
);
6413 plugActionList( "loadImages", lst
);
6418 void KHTMLPart::slotPrintFrame()
6420 if ( d
->m_frames
.count() == 0 )
6423 KParts::ReadOnlyPart
*frame
= currentFrame();
6427 KParts::BrowserExtension
*ext
= KParts::BrowserExtension::childObject( frame
);
6433 const QMetaObject
*mo
= ext
->metaObject();
6436 if (mo
->indexOfSlot( "print()") != -1)
6437 QMetaObject::invokeMethod(ext
, "print()", Qt::DirectConnection
);
6440 void KHTMLPart::slotSelectAll()
6442 KParts::ReadOnlyPart
*part
= currentFrame();
6443 if (part
&& part
->inherits("KHTMLPart"))
6444 static_cast<KHTMLPart
*>(part
)->selectAll();
6447 void KHTMLPart::startAutoScroll()
6449 connect(&d
->m_scrollTimer
, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
6450 d
->m_scrollTimer
.setSingleShot(false);
6451 d
->m_scrollTimer
.start(100);
6454 void KHTMLPart::stopAutoScroll()
6456 disconnect(&d
->m_scrollTimer
, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
6457 if (d
->m_scrollTimer
.isActive())
6458 d
->m_scrollTimer
.stop();
6462 void KHTMLPart::slotAutoScroll()
6465 d
->m_view
->doAutoScroll();
6467 stopAutoScroll(); // Safety
6470 void KHTMLPart::runAdFilter()
6473 parentPart()->runAdFilter();
6478 QSetIterator
<khtml::CachedObject
*> it( d
->m_doc
->docLoader()->m_docObjects
);
6479 while (it
.hasNext())
6481 khtml::CachedObject
* obj
= it
.next();
6482 if ( obj
->type() == khtml::CachedObject::Image
) {
6483 khtml::CachedImage
*image
= static_cast<khtml::CachedImage
*>(obj
);
6484 bool wasBlocked
= image
->m_wasBlocked
;
6485 image
->m_wasBlocked
= KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d
->m_doc
->completeURL( image
->url().string() ) );
6486 if ( image
->m_wasBlocked
!= wasBlocked
)
6487 image
->do_notify(QRect(QPoint(0,0), image
->pixmap_size()));
6491 if ( KHTMLGlobal::defaultHTMLSettings()->isHideAdsEnabled() ) {
6492 for ( NodeImpl
*nextNode
, *node
= d
->m_doc
; node
; node
= nextNode
) {
6494 // We might be deleting 'node' shortly.
6495 nextNode
= node
->traverseNextNode();
6497 if ( node
->id() == ID_IMG
||
6498 node
->id() == ID_IFRAME
||
6499 (node
->id() == ID_INPUT
&& static_cast<HTMLInputElementImpl
*>(node
)->inputType() == HTMLInputElementImpl::IMAGE
))
6501 if ( KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d
->m_doc
->completeURL( static_cast<ElementImpl
*>(node
)->getAttribute(ATTR_SRC
).string() ) ) )
6503 // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
6505 NodeImpl
*parent
= node
->parent();
6509 parent
->removeChild(node
, exception
);
6518 void KHTMLPart::selectAll()
6520 if (!d
->m_doc
) return;
6523 if (d
->m_doc
->isHTMLDocument())
6524 first
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body();
6529 // Look for first text/cdata node that has a renderer,
6530 // or first childless replaced element
6531 while ( first
&& !(first
->renderer()
6532 && ((first
->nodeType() == Node::TEXT_NODE
|| first
->nodeType() == Node::CDATA_SECTION_NODE
)
6533 || (first
->renderer()->isReplaced() && !first
->renderer()->firstChild()))))
6535 next
= first
->firstChild();
6536 if ( !next
) next
= first
->nextSibling();
6537 while( first
&& !next
)
6539 first
= first
->parentNode();
6541 next
= first
->nextSibling();
6547 if (d
->m_doc
->isHTMLDocument())
6548 last
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body();
6551 // Look for last text/cdata node that has a renderer,
6552 // or last childless replaced element
6553 // ### Instead of changing this loop, use findLastSelectableNode
6554 // in render_table.cpp (LS)
6555 while ( last
&& !(last
->renderer()
6556 && ((last
->nodeType() == Node::TEXT_NODE
|| last
->nodeType() == Node::CDATA_SECTION_NODE
)
6557 || (last
->renderer()->isReplaced() && !last
->renderer()->lastChild()))))
6559 next
= last
->lastChild();
6560 if ( !next
) next
= last
->previousSibling();
6561 while ( last
&& !next
)
6563 last
= last
->parentNode();
6565 next
= last
->previousSibling();
6570 if ( !first
|| !last
)
6572 Q_ASSERT(first
->renderer());
6573 Q_ASSERT(last
->renderer());
6574 d
->editor_context
.m_selection
.moveTo(Position(first
, 0), Position(last
, last
->nodeValue().length()));
6575 d
->m_doc
->updateSelection();
6577 emitSelectionChanged();
6580 bool KHTMLPart::checkLinkSecurity(const KUrl
&linkURL
,const KLocalizedString
&message
, const QString
&button
)
6582 bool linkAllowed
= true;
6585 linkAllowed
= KAuthorized::authorizeUrlAction("redirect", url(), linkURL
);
6587 if ( !linkAllowed
) {
6588 khtml::Tokenizer
*tokenizer
= d
->m_doc
->tokenizer();
6590 tokenizer
->setOnHold(true);
6592 int response
= KMessageBox::Cancel
;
6593 if (!message
.isEmpty())
6595 response
= KMessageBox::warningContinueCancel( 0,
6596 message
.subs(Qt::escape(linkURL
.prettyUrl())).toString(),
6597 i18n( "Security Warning" ),
6602 KMessageBox::error( 0,
6603 i18n( "<qt>Access by untrusted page to<br /><b>%1</b><br /> denied.</qt>", Qt::escape(linkURL
.prettyUrl())),
6604 i18n( "Security Alert" ));
6608 tokenizer
->setOnHold(false);
6609 return (response
==KMessageBox::Continue
);
6614 void KHTMLPart::slotPartRemoved( KParts::Part
*part
)
6616 // kDebug(6050) << part;
6617 if ( part
== d
->m_activeFrame
)
6619 d
->m_activeFrame
= 0L;
6620 if ( !part
->inherits( "KHTMLPart" ) )
6623 factory()->removeClient( part
);
6625 if (childClients().contains(part
)) {
6626 removeChildClient( part
);
6632 void KHTMLPart::slotActiveFrameChanged( KParts::Part
*part
)
6634 // kDebug(6050) << this << "part=" << part;
6637 kError(6050) << "strange error! we activated ourselves";
6641 // kDebug(6050) << "d->m_activeFrame=" << d->m_activeFrame;
6642 if ( d
->m_activeFrame
&& d
->m_activeFrame
->widget() && d
->m_activeFrame
->widget()->inherits( "QFrame" ) )
6644 QFrame
*frame
= static_cast<QFrame
*>( d
->m_activeFrame
->widget() );
6645 if (frame
->frameStyle() != QFrame::NoFrame
)
6647 frame
->setFrameStyle( QFrame::StyledPanel
| QFrame::Sunken
);
6652 if( d
->m_activeFrame
&& !d
->m_activeFrame
->inherits( "KHTMLPart" ) )
6655 factory()->removeClient( d
->m_activeFrame
);
6657 removeChildClient( d
->m_activeFrame
);
6659 if( part
&& !part
->inherits( "KHTMLPart" ) )
6662 factory()->addClient( part
);
6664 insertChildClient( part
);
6668 d
->m_activeFrame
= part
;
6670 if ( d
->m_activeFrame
&& d
->m_activeFrame
->widget()->inherits( "QFrame" ) )
6672 QFrame
*frame
= static_cast<QFrame
*>( d
->m_activeFrame
->widget() );
6673 if (frame
->frameStyle() != QFrame::NoFrame
)
6675 frame
->setFrameStyle( QFrame::StyledPanel
| QFrame::Plain
);
6678 kDebug(6050) << "new active frame " << d
->m_activeFrame
;
6683 // (note: childObject returns 0 if the argument is 0)
6684 d
->m_extension
->setExtensionProxy( KParts::BrowserExtension::childObject( d
->m_activeFrame
) );
6687 void KHTMLPart::setActiveNode(const DOM::Node
&node
)
6689 if (!d
->m_doc
|| !d
->m_view
)
6692 // Set the document's active node
6693 d
->m_doc
->setFocusNode(node
.handle());
6695 // Scroll the view if necessary to ensure that the new focus node is visible
6696 QRect rect
= node
.handle()->getRect();
6697 d
->m_view
->ensureVisible(rect
.right(), rect
.bottom());
6698 d
->m_view
->ensureVisible(rect
.left(), rect
.top());
6701 DOM::Node
KHTMLPart::activeNode() const
6703 return DOM::Node(d
->m_doc
?d
->m_doc
->focusNode():0);
6706 DOM::EventListener
*KHTMLPart::createHTMLEventListener( QString code
, QString name
, NodeImpl
* node
, bool svg
)
6708 KJSProxy
*proxy
= jScript();
6713 return proxy
->createHTMLEventHandler( url().url(), name
, code
, node
, svg
);
6716 KHTMLPart
*KHTMLPart::opener()
6721 void KHTMLPart::setOpener(KHTMLPart
*_opener
)
6723 d
->m_opener
= _opener
;
6726 bool KHTMLPart::openedByJS()
6728 return d
->m_openedByJS
;
6731 void KHTMLPart::setOpenedByJS(bool _openedByJS
)
6733 d
->m_openedByJS
= _openedByJS
;
6736 void KHTMLPart::preloadStyleSheet(const QString
&url
, const QString
&stylesheet
)
6738 khtml::Cache::preloadStyleSheet(url
, stylesheet
);
6741 void KHTMLPart::preloadScript(const QString
&url
, const QString
&script
)
6743 khtml::Cache::preloadScript(url
, script
);
6746 long KHTMLPart::cacheId() const
6748 return d
->m_cacheId
;
6751 bool KHTMLPart::restored() const
6753 return d
->m_restored
;
6756 bool KHTMLPart::pluginPageQuestionAsked(const QString
& mimetype
) const
6758 // parentPart() should be const!
6759 KHTMLPart
* parent
= const_cast<KHTMLPart
*>(this)->parentPart();
6761 return parent
->pluginPageQuestionAsked(mimetype
);
6763 return d
->m_pluginPageQuestionAsked
.contains(mimetype
);
6766 void KHTMLPart::setPluginPageQuestionAsked(const QString
& mimetype
)
6769 parentPart()->setPluginPageQuestionAsked(mimetype
);
6771 d
->m_pluginPageQuestionAsked
.append(mimetype
);
6774 KEncodingDetector
*KHTMLPart::createDecoder()
6776 KEncodingDetector
*dec
= new KEncodingDetector();
6777 if( !d
->m_encoding
.isNull() )
6778 dec
->setEncoding( d
->m_encoding
.toLatin1().constData(),
6779 d
->m_haveEncoding
? KEncodingDetector::UserChosenEncoding
: KEncodingDetector::EncodingFromHTTPHeader
);
6781 // Inherit the default encoding from the parent frame if there is one.
6782 QByteArray defaultEncoding
= (parentPart() && parentPart()->d
->m_decoder
)
6783 ? QByteArray( parentPart()->d
->m_decoder
->encoding() ) : settings()->encoding().toLatin1();
6784 dec
->setEncoding(defaultEncoding
.constData(), KEncodingDetector::DefaultEncoding
);
6786 #ifdef APPLE_CHANGES
6788 d
->m_doc
->setDecoder(d
->m_decoder
);
6790 dec
->setAutoDetectLanguage( d
->m_autoDetectLanguage
);
6794 void KHTMLPart::emitCaretPositionChanged(const DOM::Position
&pos
) {
6795 // pos must not be already converted to range-compliant coordinates
6796 Position rng_pos
= pos
.equivalentRangeCompliantPosition();
6797 Node node
= rng_pos
.node();
6798 emit
caretPositionChanged(node
, rng_pos
.offset());
6801 void KHTMLPart::restoreScrollPosition()
6803 const KParts::OpenUrlArguments
args( arguments() );
6805 if ( url().hasRef() && !d
->m_restoreScrollPosition
&& !args
.reload()) {
6806 if ( !d
->m_doc
|| !d
->m_doc
->parsing() )
6807 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
6808 if ( !gotoAnchor(url().encodedHtmlRef()) )
6809 gotoAnchor(url().htmlRef());
6813 // Check whether the viewport has become large enough to encompass the stored
6814 // offsets. If the document has been fully loaded, force the new coordinates,
6815 // even if the canvas is too short (can happen when user resizes the window
6817 if (d
->m_view
->contentsHeight() - d
->m_view
->visibleHeight() >= args
.yOffset()
6818 || d
->m_bComplete
) {
6819 d
->m_view
->setContentsPos(args
.xOffset(), args
.yOffset());
6820 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
6825 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl
*form
)
6827 #ifndef KHTML_NO_WALLET
6830 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart()) {
6834 p
->openWallet(form
);
6838 if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
6843 if (d
->m_bWalletOpened
) {
6844 if (d
->m_wallet
->isOpen()) {
6845 form
->walletOpened(d
->m_wallet
);
6848 d
->m_wallet
->deleteLater();
6850 d
->m_bWalletOpened
= false;
6855 KWallet::Wallet
*wallet
= KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous
);
6856 d
->m_wq
= new KHTMLWalletQueue(this);
6857 d
->m_wq
->wallet
= wallet
;
6858 connect(wallet
, SIGNAL(walletOpened(bool)), d
->m_wq
, SLOT(walletOpened(bool)));
6859 connect(d
->m_wq
, SIGNAL(walletOpened(KWallet::Wallet
*)), this, SLOT(walletOpened(KWallet::Wallet
*)));
6862 d
->m_wq
->callers
.append(KHTMLWalletQueue::Caller(form
, form
->document()));
6863 #endif // KHTML_NO_WALLET
6867 void KHTMLPart::saveToWallet(const QString
& key
, const QMap
<QString
,QString
>& data
)
6869 #ifndef KHTML_NO_WALLET
6872 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart()) {
6876 p
->saveToWallet(key
, data
);
6881 if (d
->m_bWalletOpened
) {
6882 if (d
->m_wallet
->isOpen()) {
6883 if (!d
->m_wallet
->hasFolder(KWallet::Wallet::FormDataFolder())) {
6884 d
->m_wallet
->createFolder(KWallet::Wallet::FormDataFolder());
6886 d
->m_wallet
->setFolder(KWallet::Wallet::FormDataFolder());
6887 d
->m_wallet
->writeMap(key
, data
);
6890 d
->m_wallet
->deleteLater();
6892 d
->m_bWalletOpened
= false;
6897 KWallet::Wallet
*wallet
= KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous
);
6898 d
->m_wq
= new KHTMLWalletQueue(this);
6899 d
->m_wq
->wallet
= wallet
;
6900 connect(wallet
, SIGNAL(walletOpened(bool)), d
->m_wq
, SLOT(walletOpened(bool)));
6901 connect(d
->m_wq
, SIGNAL(walletOpened(KWallet::Wallet
*)), this, SLOT(walletOpened(KWallet::Wallet
*)));
6903 d
->m_wq
->savers
.append(qMakePair(key
, data
));
6904 #endif // KHTML_NO_WALLET
6908 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl
*form
) {
6909 #ifndef KHTML_NO_WALLET
6912 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart()) {
6916 p
->dequeueWallet(form
);
6921 d
->m_wq
->callers
.removeAll(KHTMLWalletQueue::Caller(form
, form
->document()));
6923 #endif // KHTML_NO_WALLET
6927 void KHTMLPart::walletOpened(KWallet::Wallet
*wallet
) {
6928 #ifndef KHTML_NO_WALLET
6929 assert(!d
->m_wallet
);
6932 d
->m_wq
->deleteLater(); // safe?
6936 d
->m_bWalletOpened
= false;
6940 d
->m_wallet
= wallet
;
6941 d
->m_bWalletOpened
= true;
6942 connect(d
->m_wallet
, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
6944 if (!d
->m_statusBarWalletLabel
) {
6945 d
->m_statusBarWalletLabel
= new KUrlLabel(d
->m_statusBarExtension
->statusBar());
6946 d
->m_statusBarWalletLabel
->setFixedHeight(KHTMLGlobal::iconLoader()->currentSize(KIconLoader::Small
));
6947 d
->m_statusBarWalletLabel
->setSizePolicy(QSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
));
6948 d
->m_statusBarWalletLabel
->setUseCursor(false);
6949 d
->m_statusBarExtension
->addStatusBarItem(d
->m_statusBarWalletLabel
, 0, false);
6950 d
->m_statusBarWalletLabel
->setPixmap(SmallIcon("wallet-open"));
6951 connect(d
->m_statusBarWalletLabel
, SIGNAL(leftClickedUrl()), SLOT(launchWalletManager()));
6952 connect(d
->m_statusBarWalletLabel
, SIGNAL(rightClickedUrl()), SLOT(walletMenu()));
6954 d
->m_statusBarWalletLabel
->setToolTip(i18n("The wallet '%1' is open and being used for form data and passwords.", KWallet::Wallet::NetworkWallet()));
6955 #endif // KHTML_NO_WALLET
6959 KWallet::Wallet
*KHTMLPart::wallet()
6961 #ifndef KHTML_NO_WALLET
6964 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart())
6973 #endif // !KHTML_NO_WALLET
6977 void KHTMLPart::slotWalletClosed()
6979 #ifndef KHTML_NO_WALLET
6981 d
->m_wallet
->deleteLater();
6984 d
->m_bWalletOpened
= false;
6985 if (d
->m_statusBarWalletLabel
) {
6986 d
->m_statusBarExtension
->removeStatusBarItem(d
->m_statusBarWalletLabel
);
6987 delete d
->m_statusBarWalletLabel
;
6988 d
->m_statusBarWalletLabel
= 0L;
6990 #endif // KHTML_NO_WALLET
6993 void KHTMLPart::launchWalletManager()
6995 #ifndef KHTML_NO_WALLET
6996 QDBusInterface
r("org.kde.kwalletmanager", "/kwalletmanager/MainWindow_1",
6997 "org.kde.KMainWindow");
6999 KToolInvocation::startServiceByDesktopName("kwalletmanager_show");
7001 r
.call(QDBus::NoBlock
, "show");
7002 r
.call(QDBus::NoBlock
, "raise");
7004 #endif // KHTML_NO_WALLET
7007 void KHTMLPart::walletMenu()
7009 #ifndef KHTML_NO_WALLET
7010 KMenu
*m
= new KMenu(0L);
7011 m
->addAction(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
7012 m
->popup(QCursor::pos());
7013 #endif // KHTML_NO_WALLET
7016 void KHTMLPart::slotToggleCaretMode()
7018 setCaretMode(d
->m_paToggleCaretMode
->isChecked());
7021 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn
) {
7022 d
->m_formNotification
= fn
;
7025 KHTMLPart::FormNotification
KHTMLPart::formNotification() const {
7026 return d
->m_formNotification
;
7029 KUrl
KHTMLPart::toplevelURL()
7031 KHTMLPart
* part
= this;
7032 while (part
->parentPart())
7033 part
= part
->parentPart();
7041 bool KHTMLPart::isModified() const
7046 return d
->m_doc
->unsubmittedFormChanges();
7049 void KHTMLPart::setDebugScript( bool enable
)
7051 unplugActionList( "debugScriptList" );
7053 if (!d
->m_paDebugScript
) {
7054 d
->m_paDebugScript
= new KAction( i18n( "JavaScript &Debugger" ), this );
7055 actionCollection()->addAction( "debugScript", d
->m_paDebugScript
);
7056 connect( d
->m_paDebugScript
, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugScript() ) );
7058 d
->m_paDebugScript
->setEnabled( d
->m_frame
? d
->m_frame
->m_jscript
: 0L );
7059 QList
<QAction
*> lst
;
7060 lst
.append( d
->m_paDebugScript
);
7061 plugActionList( "debugScriptList", lst
);
7063 d
->m_bJScriptDebugEnabled
= enable
;
7066 void KHTMLPart::setSuppressedPopupIndicator( bool enable
, KHTMLPart
*originPart
)
7068 if ( parentPart() ) {
7069 parentPart()->setSuppressedPopupIndicator( enable
, originPart
);
7073 if ( enable
&& originPart
) {
7074 d
->m_openableSuppressedPopups
++;
7075 if ( d
->m_suppressedPopupOriginParts
.indexOf( originPart
) == -1 )
7076 d
->m_suppressedPopupOriginParts
.append( originPart
);
7079 if ( enable
&& !d
->m_statusBarPopupLabel
) {
7080 d
->m_statusBarPopupLabel
= new KUrlLabel( d
->m_statusBarExtension
->statusBar() );
7081 d
->m_statusBarPopupLabel
->setFixedHeight( KHTMLGlobal::iconLoader()->currentSize( KIconLoader::Small
) );
7082 d
->m_statusBarPopupLabel
->setSizePolicy( QSizePolicy( QSizePolicy::Fixed
, QSizePolicy::Fixed
));
7083 d
->m_statusBarPopupLabel
->setUseCursor( false );
7084 d
->m_statusBarExtension
->addStatusBarItem( d
->m_statusBarPopupLabel
, 0, false );
7085 d
->m_statusBarPopupLabel
->setPixmap( SmallIcon( "window-suppressed") );
7087 d
->m_statusBarPopupLabel
->setToolTip(i18n("This page was prevented from opening a new window via JavaScript." ) );
7089 connect(d
->m_statusBarPopupLabel
, SIGNAL(leftClickedUrl()), SLOT(suppressedPopupMenu()));
7090 if (d
->m_settings
->jsPopupBlockerPassivePopup()) {
7092 px
= MainBarIcon( "window-suppressed" );
7093 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
);
7095 } else if ( !enable
&& d
->m_statusBarPopupLabel
) {
7096 d
->m_statusBarPopupLabel
->setToolTip("" );
7097 d
->m_statusBarExtension
->removeStatusBarItem( d
->m_statusBarPopupLabel
);
7098 delete d
->m_statusBarPopupLabel
;
7099 d
->m_statusBarPopupLabel
= 0L;
7103 void KHTMLPart::suppressedPopupMenu() {
7104 KMenu
*m
= new KMenu(0L);
7105 if ( d
->m_openableSuppressedPopups
)
7106 m
->addAction(i18np("&Show Blocked Popup Window","&Show %1 Blocked Popup Windows", d
->m_openableSuppressedPopups
), this, SLOT(showSuppressedPopups()));
7107 QAction
*a
= m
->addAction(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()));
7108 a
->setChecked(d
->m_settings
->jsPopupBlockerPassivePopup());
7109 m
->addAction(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
7110 m
->popup(QCursor::pos());
7113 void KHTMLPart::togglePopupPassivePopup() {
7114 // Same hack as in disableJSErrorExtension()
7115 d
->m_settings
->setJSPopupBlockerPassivePopup( !d
->m_settings
->jsPopupBlockerPassivePopup() );
7116 emit
configurationChanged();
7119 void KHTMLPart::showSuppressedPopups() {
7120 foreach ( KHTMLPart
* part
, d
->m_suppressedPopupOriginParts
) {
7122 KJS::Window
*w
= KJS::Window::retrieveWindow( part
);
7124 w
->showSuppressedWindows();
7125 w
->forgetSuppressedWindows();
7129 setSuppressedPopupIndicator( false );
7130 d
->m_openableSuppressedPopups
= 0;
7131 d
->m_suppressedPopupOriginParts
.clear();
7134 // Extension to use for "view document source", "save as" etc.
7135 // Using the right extension can help the viewer get into the right mode (#40496)
7136 QString
KHTMLPart::defaultExtension() const
7140 if ( !d
->m_doc
->isHTMLDocument() )
7142 return d
->m_doc
->htmlMode() == DOM::DocumentImpl::XHtml
? ".xhtml" : ".html";
7145 bool KHTMLPart::inProgress() const
7147 if (!d
->m_bComplete
|| d
->m_runningScripts
|| (d
->m_doc
&& d
->m_doc
->parsing()))
7150 // Any frame that hasn't completed yet ?
7151 ConstFrameIt it
= d
->m_frames
.constBegin();
7152 const ConstFrameIt end
= d
->m_frames
.constEnd();
7153 for (; it
!= end
; ++it
) {
7154 if ((*it
)->m_run
|| !(*it
)->m_bCompleted
)
7158 return d
->m_submitForm
|| !d
->m_redirectURL
.isEmpty() || d
->m_redirectionTimer
.isActive() || d
->m_job
;
7161 using namespace KParts
;
7162 #include "khtml_part.moc"
7163 #include "khtmlpart_p.moc"
7164 #ifndef KHTML_NO_WALLET
7165 #include "khtml_wallet_p.moc"