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 <kstandardguiitem.h>
94 #include <kactioncollection.h>
95 #include <kfiledialog.h>
96 #include <kmimetypetrader.h>
97 #include <ktemporaryfile.h>
98 #include <kglobalsettings.h>
99 #include <ktoolinvocation.h>
100 #include <kauthorized.h>
101 #include <kparts/browserinterface.h>
102 #include <kde_file.h>
103 #include <kactionmenu.h>
104 #include <ktoggleaction.h>
105 #include <kcodecaction.h>
106 #include <kselectaction.h>
108 #include <ksslinfodialog.h>
110 #include <kfileitem.h>
111 #include <kurifilter.h>
112 #include <kstatusbar.h>
113 #include <kurllabel.h>
115 #include <QtGui/QClipboard>
116 #include <QtCore/QFile>
117 #include <QtCore/QMetaEnum>
118 #include <QtGui/QTextDocument>
119 #include <QtCore/QDate>
120 #include <QtNetwork/QSslCertificate>
122 #include "khtmlpart_p.h"
123 #include "khtml_iface.h"
124 #include "kpassivepopup.h"
126 #include "rendering/render_form.h"
127 #include <kwindowsystem.h>
128 #include <kconfiggroup.h>
130 #include "ecma/debugger/debugwindow.h"
133 #include <svg/SVGDocument.h>
135 bool KHTMLPartPrivate::s_dnsInitialised
= false;
137 // DNS prefetch settings
138 static const int sMaxDNSPrefetchPerPage
= 42;
139 static const int sDNSPrefetchTimerDelay
= 200;
140 static const int sDNSTTLSeconds
= 400;
141 static const int sDNSCacheSize
= 500;
146 class PartStyleSheetLoader
: public CachedObjectClient
149 PartStyleSheetLoader(KHTMLPart
*part
, DOM::DOMString url
, DocLoader
* dl
)
152 m_cachedSheet
= dl
->requestStyleSheet(url
, QString(), "text/css",
153 true /* "user sheet" */);
155 m_cachedSheet
->ref( this );
157 virtual ~PartStyleSheetLoader()
159 if ( m_cachedSheet
) m_cachedSheet
->deref(this);
161 virtual void setStyleSheet(const DOM::DOMString
&, const DOM::DOMString
&sheet
, const DOM::DOMString
&, const DOM::DOMString
&/*mimetype*/)
164 m_part
->setUserStyleSheet( sheet
.string() );
168 virtual void error( int, const QString
& ) {
171 QPointer
<KHTMLPart
> m_part
;
172 khtml::CachedCSSStyleSheet
*m_cachedSheet
;
176 void khtml::ChildFrame::liveConnectEvent(const unsigned long, const QString
& event
, const KParts::LiveConnectExtension::ArgList
& args
)
178 if (!m_part
|| !m_partContainerElement
|| !m_liveconnect
)
183 script
.sprintf("%s(", event
.toLatin1().constData());
185 KParts::LiveConnectExtension::ArgList::const_iterator i
= args
.begin();
186 const KParts::LiveConnectExtension::ArgList::const_iterator argsBegin
= i
;
187 const KParts::LiveConnectExtension::ArgList::const_iterator argsEnd
= args
.end();
189 for ( ; i
!= argsEnd
; ++i
) {
192 if ((*i
).first
== KParts::LiveConnectExtension::TypeString
) {
194 script
+= QString((*i
).second
).replace('\\', "\\\\").replace('"', "\\\"");
197 script
+= (*i
).second
;
200 kDebug(6050) << script
;
202 KHTMLPart
* part
= qobject_cast
<KHTMLPart
*>(m_part
->parent());
206 part
->framejScript(m_part
);
208 // we have a jscript => a part in an iframe
210 m_jscript
->evaluate(QString(), 1, script
, 0L, &cmp
);
212 part
->executeScript(DOM::Node(m_partContainerElement
), script
);
215 KHTMLFrameList::Iterator
KHTMLFrameList::find( const QString
&name
)
217 Iterator it
= begin();
218 const Iterator e
= end();
221 if ( (*it
)->m_name
==name
)
227 KHTMLPart::KHTMLPart( QWidget
*parentWidget
, QObject
*parent
, GUIProfile prof
)
228 : KParts::ReadOnlyPart( parent
)
231 KHTMLGlobal::registerPart( this );
232 setComponentData( KHTMLGlobal::componentData(), false );
233 init( new KHTMLView( this, parentWidget
), prof
);
236 KHTMLPart::KHTMLPart( KHTMLView
*view
, QObject
*parent
, GUIProfile prof
)
237 : KParts::ReadOnlyPart( parent
)
240 KHTMLGlobal::registerPart( this );
241 setComponentData( KHTMLGlobal::componentData(), false );
244 view
->setPart( this );
248 void KHTMLPart::init( KHTMLView
*view
, GUIProfile prof
)
250 if ( prof
== DefaultGUI
)
251 setXMLFile( "khtml.rc" );
252 else if ( prof
== BrowserViewGUI
)
253 setXMLFile( "khtml_browser.rc" );
255 d
= new KHTMLPartPrivate(this, parent());
260 QWidget
*widget
= new QWidget( view
->parentWidget() );
261 widget
->setObjectName("khtml_part_widget");
262 QVBoxLayout
*layout
= new QVBoxLayout( widget
);
263 layout
->setContentsMargins( 0, 0, 0, 0 );
264 layout
->setSpacing( 0 );
265 widget
->setLayout( layout
);
267 d
->m_topViewBar
= new KHTMLViewBar( KHTMLViewBar::Top
, d
->m_view
, widget
);
268 d
->m_bottomViewBar
= new KHTMLViewBar( KHTMLViewBar::Bottom
, d
->m_view
, widget
);
270 layout
->addWidget( d
->m_topViewBar
);
271 layout
->addWidget( d
->m_view
);
272 layout
->addWidget( d
->m_bottomViewBar
);
274 widget
->setFocusProxy( d
->m_view
);
279 d
->m_guiProfile
= prof
;
280 d
->m_extension
= new KHTMLPartBrowserExtension( this );
281 d
->m_extension
->setObjectName( "KHTMLBrowserExtension" );
282 d
->m_hostExtension
= new KHTMLPartBrowserHostExtension( this );
283 d
->m_statusBarExtension
= new KParts::StatusBarExtension( this );
284 d
->m_statusBarPopupLabel
= 0L;
285 d
->m_openableSuppressedPopups
= 0;
287 d
->m_paLoadImages
= 0;
288 d
->m_paDebugScript
= 0;
289 d
->m_bMousePressed
= false;
290 d
->m_bRightMousePressed
= false;
291 d
->m_bCleared
= false;
293 if ( prof
== BrowserViewGUI
) {
294 d
->m_paViewDocument
= new KAction( i18n( "View Do&cument Source" ), this );
295 actionCollection()->addAction( "viewDocumentSource", d
->m_paViewDocument
);
296 connect( d
->m_paViewDocument
, SIGNAL( triggered( bool ) ), this, SLOT( slotViewDocumentSource() ) );
298 d
->m_paViewDocument
->setShortcut( QKeySequence(Qt::CTRL
+ Qt::Key_U
) );
299 d
->m_paViewDocument
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
302 d
->m_paViewFrame
= new KAction( i18n( "View Frame Source" ), this );
303 actionCollection()->addAction( "viewFrameSource", d
->m_paViewFrame
);
304 connect( d
->m_paViewFrame
, SIGNAL( triggered( bool ) ), this, SLOT( slotViewFrameSource() ) );
306 d
->m_paViewFrame
->setShortcut( QKeySequence(Qt::CTRL
+ Qt::SHIFT
+ Qt::Key_U
) );
307 d
->m_paViewFrame
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
310 d
->m_paViewInfo
= new KAction( i18n( "View Document Information" ), this );
311 actionCollection()->addAction( "viewPageInfo", d
->m_paViewInfo
);
313 d
->m_paViewInfo
->setShortcut( QKeySequence(Qt::CTRL
+Qt::Key_I
) );
314 d
->m_paViewInfo
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
316 connect( d
->m_paViewInfo
, SIGNAL( triggered( bool ) ), this, SLOT( slotViewPageInfo() ) );
318 d
->m_paSaveBackground
= new KAction( i18n( "Save &Background Image As..." ), this );
319 actionCollection()->addAction( "saveBackground", d
->m_paSaveBackground
);
320 connect( d
->m_paSaveBackground
, SIGNAL( triggered( bool ) ), this, SLOT( slotSaveBackground() ) );
322 d
->m_paSaveDocument
= actionCollection()->addAction( KStandardAction::SaveAs
, "saveDocument",
323 this, SLOT( slotSaveDocument() ) );
325 d
->m_paSaveDocument
->setShortcuts( KShortcut() ); // avoid clashes
327 d
->m_paSaveFrame
= new KAction( i18n( "Save &Frame As..." ), this );
328 actionCollection()->addAction( "saveFrame", d
->m_paSaveFrame
);
329 connect( d
->m_paSaveFrame
, SIGNAL( triggered( bool ) ), this, SLOT( slotSaveFrame() ) );
331 d
->m_paViewDocument
= 0;
332 d
->m_paViewFrame
= 0;
334 d
->m_paSaveBackground
= 0;
335 d
->m_paSaveDocument
= 0;
336 d
->m_paSaveFrame
= 0;
339 d
->m_paSecurity
= new KAction( i18n( "SSL" ), this );
340 actionCollection()->addAction( "security", d
->m_paSecurity
);
341 connect( d
->m_paSecurity
, SIGNAL( triggered( bool ) ), this, SLOT( slotSecurity() ) );
343 d
->m_paDebugRenderTree
= new KAction( i18n( "Print Rendering Tree to STDOUT" ), this );
344 actionCollection()->addAction( "debugRenderTree", d
->m_paDebugRenderTree
);
345 connect( d
->m_paDebugRenderTree
, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugRenderTree() ) );
347 d
->m_paDebugDOMTree
= new KAction( i18n( "Print DOM Tree to STDOUT" ), this );
348 actionCollection()->addAction( "debugDOMTree", d
->m_paDebugDOMTree
);
349 connect( d
->m_paDebugDOMTree
, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugDOMTree() ) );
351 d
->m_paStopAnimations
= new KAction( i18n( "Stop Animated Images" ), this );
352 actionCollection()->addAction( "stopAnimations", d
->m_paStopAnimations
);
353 connect( d
->m_paStopAnimations
, SIGNAL( triggered( bool ) ), this, SLOT( slotStopAnimations() ) );
355 d
->m_paSetEncoding
= new KCodecAction( KIcon("character-set"), i18n( "Set &Encoding" ), this, true );
356 actionCollection()->addAction( "setEncoding", d
->m_paSetEncoding
);
357 // d->m_paSetEncoding->setDelayed( false );
359 connect( d
->m_paSetEncoding
, SIGNAL(triggered(const QString
&)), this, SLOT( slotSetEncoding(const QString
&)));
360 connect( d
->m_paSetEncoding
, SIGNAL(triggered(KEncodingDetector::AutoDetectScript
)), this, SLOT( slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript
)));
362 if ( KGlobal::config()->hasGroup( "HTML Settings" ) ) {
363 KConfigGroup
config( KGlobal::config(), "HTML Settings" );
365 d
->m_autoDetectLanguage
= static_cast<KEncodingDetector::AutoDetectScript
>(config
.readEntry( "AutomaticDetectionLanguage", /*static_cast<int>(language) */0));
366 if (d
->m_autoDetectLanguage
==KEncodingDetector::None
) {
367 const QByteArray name
= KGlobal::locale()->encoding().toLower();
368 // kWarning() << "00000000 ";
369 if (name
.endsWith("1251")||name
.startsWith("koi")||name
=="iso-8859-5")
370 d
->m_autoDetectLanguage
=KEncodingDetector::Cyrillic
;
371 else if (name
.endsWith("1256")||name
=="iso-8859-6")
372 d
->m_autoDetectLanguage
=KEncodingDetector::Arabic
;
373 else if (name
.endsWith("1257")||name
=="iso-8859-13"||name
=="iso-8859-4")
374 d
->m_autoDetectLanguage
=KEncodingDetector::Baltic
;
375 else if (name
.endsWith("1250")|| name
=="ibm852" || name
=="iso-8859-2" || name
=="iso-8859-3" )
376 d
->m_autoDetectLanguage
=KEncodingDetector::CentralEuropean
;
377 else if (name
.endsWith("1253")|| name
=="iso-8859-7" )
378 d
->m_autoDetectLanguage
=KEncodingDetector::Greek
;
379 else if (name
.endsWith("1255")|| name
=="iso-8859-8" || name
=="iso-8859-8-i" )
380 d
->m_autoDetectLanguage
=KEncodingDetector::Hebrew
;
381 else if (name
=="jis7" || name
=="eucjp" || name
=="sjis" )
382 d
->m_autoDetectLanguage
=KEncodingDetector::Japanese
;
383 else if (name
.endsWith("1254")|| name
=="iso-8859-9" )
384 d
->m_autoDetectLanguage
=KEncodingDetector::Turkish
;
385 else if (name
.endsWith("1252")|| name
=="iso-8859-1" || name
=="iso-8859-15" )
386 d
->m_autoDetectLanguage
=KEncodingDetector::WesternEuropean
;
388 d
->m_autoDetectLanguage
=KEncodingDetector::SemiautomaticDetection
;
389 // kWarning() << "0000000end " << d->m_autoDetectLanguage << " " << KGlobal::locale()->encodingMib();
391 d
->m_paSetEncoding
->setCurrentAutoDetectScript(d
->m_autoDetectLanguage
);
394 d
->m_paUseStylesheet
= new KSelectAction( i18n( "Use S&tylesheet"), this );
395 actionCollection()->addAction( "useStylesheet", d
->m_paUseStylesheet
);
396 connect( d
->m_paUseStylesheet
, SIGNAL( triggered( int ) ), this, SLOT( slotUseStylesheet() ) );
398 if ( prof
== BrowserViewGUI
) {
399 d
->m_paIncZoomFactor
= new KHTMLZoomFactorAction( this, true, "format-font-size-more", i18n( "Enlarge Font" ), this );
400 actionCollection()->addAction( "incFontSizes", d
->m_paIncZoomFactor
);
401 connect(d
->m_paIncZoomFactor
, SIGNAL(triggered(bool)), SLOT( slotIncFontSizeFast() ));
402 d
->m_paIncZoomFactor
->setWhatsThis( i18n( "Enlarge Font<br /><br />"
403 "Make the font in this window bigger. "
404 "Click and hold down the mouse button for a menu with all available font sizes." ) );
406 d
->m_paDecZoomFactor
= new KHTMLZoomFactorAction( this, false, "format-font-size-less", i18n( "Shrink Font" ), this );
407 actionCollection()->addAction( "decFontSizes", d
->m_paDecZoomFactor
);
408 connect(d
->m_paDecZoomFactor
, SIGNAL(triggered(bool)), SLOT( slotDecFontSizeFast() ));
409 d
->m_paDecZoomFactor
->setWhatsThis( i18n( "Shrink Font<br /><br />"
410 "Make the font in this window smaller. "
411 "Click and hold down the mouse button for a menu with all available font sizes." ) );
413 // For framesets, this action also affects frames, so only
414 // the frameset needs to define a shortcut for the action.
416 // TODO: Why also CTRL+=? Because of http://trolltech.com/developer/knowledgebase/524/?
417 // Nobody else does it...
418 d
->m_paIncZoomFactor
->setShortcut( KShortcut("CTRL++; CTRL+=") );
419 d
->m_paDecZoomFactor
->setShortcut( QKeySequence(Qt::CTRL
+ Qt::Key_Minus
) );
420 d
->m_paIncZoomFactor
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
421 d
->m_paDecZoomFactor
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
425 d
->m_paFind
= actionCollection()->addAction( KStandardAction::Find
, "find", this, SLOT( slotFind() ) );
426 d
->m_paFind
->setShortcutContext( Qt::WidgetWithChildrenShortcut
); // default context conflicts when splitting konqueror
427 d
->m_paFind
->setWhatsThis( i18n( "Find text<br /><br />"
428 "Shows a dialog that allows you to find text on the displayed page." ) );
430 d
->m_paFindNext
= actionCollection()->addAction( KStandardAction::FindNext
, "findNext", this, SLOT( slotFindNext() ) );
431 d
->m_paFindNext
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
432 d
->m_paFindNext
->setWhatsThis( i18n( "Find next<br /><br />"
433 "Find the next occurrence of the text that you "
434 "have found using the <b>Find Text</b> function" ) );
436 d
->m_paFindPrev
= actionCollection()->addAction( KStandardAction::FindPrev
, "findPrevious",
437 this, SLOT( slotFindPrev() ) );
438 d
->m_paFindPrev
->setWhatsThis( i18n( "Find previous<br /><br />"
439 "Find the previous occurrence of the text that you "
440 "have found using the <b>Find Text</b> function" ) );
442 d
->m_paFindAheadText
= new KAction( i18n("Find Text as You Type"), this );
443 actionCollection()->addAction( "findAheadText", d
->m_paFindAheadText
);
444 d
->m_paFindAheadText
->setShortcuts( KShortcut( '/' ) );
445 connect( d
->m_paFindAheadText
, SIGNAL( triggered( bool ) ), this, SLOT( slotFindAheadText()) );
447 d
->m_paFindAheadLinks
= new KAction( i18n("Find Links as You Type"), this );
448 actionCollection()->addAction( "findAheadLink", d
->m_paFindAheadLinks
);
449 d
->m_paFindAheadLinks
->setShortcuts( KShortcut( '\'' ) );
450 connect( d
->m_paFindAheadLinks
, SIGNAL( triggered( bool ) ), this, SLOT( slotFindAheadLink() ) );
452 d
->m_paFindAheadText
->setEnabled( false );
453 d
->m_paFindAheadLinks
->setEnabled( false );
457 d
->m_paFind
->setShortcuts( KShortcut() ); // avoid clashes
458 d
->m_paFindNext
->setShortcuts( KShortcut() ); // avoid clashes
459 d
->m_paFindPrev
->setShortcuts( KShortcut() ); // avoid clashes
460 d
->m_paFindAheadText
->setShortcuts( KShortcut());
461 d
->m_paFindAheadLinks
->setShortcuts( KShortcut());
464 d
->m_paPrintFrame
= new KAction( i18n( "Print Frame..." ), this );
465 actionCollection()->addAction( "printFrame", d
->m_paPrintFrame
);
466 d
->m_paPrintFrame
->setIcon( KIcon( "document-print-frame" ) );
467 connect( d
->m_paPrintFrame
, SIGNAL( triggered( bool ) ), this, SLOT( slotPrintFrame() ) );
468 d
->m_paPrintFrame
->setWhatsThis( i18n( "Print Frame<br /><br />"
469 "Some pages have several frames. To print only a single frame, click "
470 "on it and then use this function." ) );
472 // Warning: The name selectAll is used hardcoded by some 3rd parties to remove the
473 // shortcut for selectAll so they do not get ambigous shortcuts. Renaming it
474 // will either crash or render useless that workaround. It would be better
475 // to use the name KStandardAction::name(KStandardAction::SelectAll) but we
476 // can't for the same reason.
477 d
->m_paSelectAll
= actionCollection()->addAction( KStandardAction::SelectAll
, "selectAll",
478 this, SLOT( slotSelectAll() ) );
479 d
->m_paSelectAll
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
480 if ( parentPart() ) // Only the frameset has the shortcut, but the slot uses the current frame.
481 d
->m_paSelectAll
->setShortcuts( KShortcut() ); // avoid clashes
483 d
->m_paToggleCaretMode
= new KToggleAction(i18n("Toggle Caret Mode"), this );
484 actionCollection()->addAction( "caretMode", d
->m_paToggleCaretMode
);
485 d
->m_paToggleCaretMode
->setShortcut( QKeySequence(Qt::Key_F7
) );
486 d
->m_paToggleCaretMode
->setShortcutContext( Qt::WidgetWithChildrenShortcut
);
487 connect( d
->m_paToggleCaretMode
, SIGNAL( triggered( bool ) ), this, SLOT(slotToggleCaretMode()) );
488 d
->m_paToggleCaretMode
->setChecked(isCaretMode());
490 d
->m_paToggleCaretMode
->setShortcut(KShortcut()); // avoid clashes
492 // set the default java(script) flags according to the current host.
493 d
->m_bOpenMiddleClick
= d
->m_settings
->isOpenMiddleClickEnabled();
494 d
->m_bBackRightClick
= d
->m_settings
->isBackRightClickEnabled();
495 d
->m_bJScriptEnabled
= d
->m_settings
->isJavaScriptEnabled();
496 setDebugScript( d
->m_settings
->isJavaScriptDebugEnabled() );
497 d
->m_bJavaEnabled
= d
->m_settings
->isJavaEnabled();
498 d
->m_bPluginsEnabled
= d
->m_settings
->isPluginsEnabled();
500 // Set the meta-refresh flag...
501 d
->m_metaRefreshEnabled
= d
->m_settings
->isAutoDelayedActionsEnabled ();
503 KHTMLSettings::KSmoothScrollingMode ssm
= d
->m_settings
->smoothScrolling();
504 if (ssm
== KHTMLSettings::KSmoothScrollingDisabled
)
505 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled
);
506 else if (ssm
== KHTMLSettings::KSmoothScrollingWhenEfficient
)
507 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient
);
509 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled
);
511 if (d
->m_bDNSPrefetchIsDefault
&& !onlyLocalReferences()) {
512 KHTMLSettings::KDNSPrefetch dpm
= d
->m_settings
->dnsPrefetch();
513 if (dpm
== KHTMLSettings::KDNSPrefetchDisabled
)
514 d
->m_bDNSPrefetch
= DNSPrefetchDisabled
;
515 else if (dpm
== KHTMLSettings::KDNSPrefetchOnlyWWWAndSLD
)
516 d
->m_bDNSPrefetch
= DNSPrefetchOnlyWWWAndSLD
;
518 d
->m_bDNSPrefetch
= DNSPrefetchEnabled
;
521 if (!KHTMLPartPrivate::s_dnsInitialised
&& d
->m_bDNSPrefetch
!= DNSPrefetchDisabled
) {
522 KIO::HostInfo::setCacheSize( sDNSCacheSize
);
523 KIO::HostInfo::setTTL( sDNSTTLSeconds
);
524 KHTMLPartPrivate::s_dnsInitialised
= true;
527 actionCollection()->associateWidget(view
);
529 connect( view
, SIGNAL( zoomView( int ) ), SLOT( slotZoomView( int ) ) );
531 connect( this, SIGNAL( completed() ),
532 this, SLOT( updateActions() ) );
533 connect( this, SIGNAL( completed( bool ) ),
534 this, SLOT( updateActions() ) );
535 connect( this, SIGNAL( started( KIO::Job
* ) ),
536 this, SLOT( updateActions() ) );
538 connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ),
539 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ) );
540 connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader
*, khtml::CachedObject
*) ),
541 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
542 connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader
*, khtml::CachedObject
*) ),
543 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
545 connect ( &d
->m_progressUpdateTimer
, SIGNAL( timeout() ), this, SLOT( slotProgressUpdate() ) );
547 findTextBegin(); //reset find variables
549 connect( &d
->m_redirectionTimer
, SIGNAL( timeout() ),
550 this, SLOT( slotRedirect() ) );
552 if (QDBusConnection::sessionBus().isConnected()) {
553 new KHTMLPartIface(this); // our "adaptor"
554 for (int i
= 1; ; ++i
)
555 if (QDBusConnection::sessionBus().registerObject(QString("/KHTML/%1/widget").arg(i
), this))
557 else if (i
== 0xffff)
558 kFatal() << "Something is very wrong in KHTMLPart!";
561 if (prof
== BrowserViewGUI
&& !parentPart())
564 // "khtml" catalog does not exist, our translations are in kdelibs.
565 // removing this catalog from KGlobal::locale() prevents problems
566 // with changing the language in applications at runtime -Thomas Reitelbach
567 // DF: a better fix would be to set the right catalog name in the KComponentData!
568 KGlobal::locale()->removeCatalog("khtml");
571 KHTMLPart::~KHTMLPart()
573 kDebug(6050) << this;
574 KConfigGroup
config( KGlobal::config(), "HTML Settings" );
575 config
.writeEntry( "AutomaticDetectionLanguage", int(d
->m_autoDetectLanguage
) );
578 if (!parentPart()) { // only delete it if the top khtml_part closes
579 removeJSErrorExtension();
580 delete d
->m_statusBarPopupLabel
;
585 d
->m_manager
->setActivePart( 0 );
586 // We specify "this" as parent qobject for d->manager, so no need to delete it.
590 d
->m_redirectionTimer
.stop();
595 disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ),
596 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader
*, khtml::CachedObject
* ) ) );
597 disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader
*, khtml::CachedObject
*) ),
598 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
599 disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader
*, khtml::CachedObject
*) ),
600 this, SLOT( slotLoaderRequestDone( khtml::DocLoader
*, khtml::CachedObject
*) ) );
607 d
->m_view
->viewport()->hide();
608 d
->m_view
->m_part
= 0;
611 // Have to delete this here since we forward declare it in khtmlpart_p and
612 // at least some compilers won't call the destructor in this case.
616 if (!parentPart()) // only delete d->m_frame if the top khtml_part closes
619 KHTMLGlobal::deregisterPart( this );
622 bool KHTMLPart::restoreURL( const KUrl
&url
)
624 kDebug( 6050 ) << url
;
626 d
->m_redirectionTimer
.stop();
629 * That's not a good idea as it will call closeUrl() on all
630 * child frames, preventing them from further loading. This
631 * method gets called from restoreState() in case of a full frameset
632 * restoral, and restoreState() calls closeUrl() before restoring
634 kDebug( 6050 ) << "closing old URL";
638 d
->m_bComplete
= false;
639 d
->m_bLoadEventEmitted
= false;
640 d
->m_workingURL
= url
;
642 // set the java(script) flags according to the current host.
643 d
->m_bJScriptEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaScriptEnabled(url
.host());
644 setDebugScript( KHTMLGlobal::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
645 d
->m_bJavaEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaEnabled(url
.host());
646 d
->m_bPluginsEnabled
= KHTMLGlobal::defaultHTMLSettings()->isPluginsEnabled(url
.host());
650 d
->m_restoreScrollPosition
= true;
651 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
652 connect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
654 KHTMLPageCache::self()->fetchData( d
->m_cacheId
, this, SLOT(slotRestoreData(const QByteArray
&)));
661 bool KHTMLPartPrivate::isLocalAnchorJump( const KUrl
& url
)
663 return url
.hasRef() && urlcmp( url
.url(), q
->url().url(),
664 KUrl::CompareWithoutTrailingSlash
| KUrl::CompareWithoutFragment
);
667 void KHTMLPartPrivate::executeAnchorJump( const KUrl
& url
, bool lockHistory
)
669 // Note: we want to emit openUrlNotify first thing, to make the history capture the old state.
671 emit m_extension
->openUrlNotify();
673 if ( !q
->gotoAnchor( url
.encodedHtmlRef()) )
674 q
->gotoAnchor( url
.htmlRef() );
677 emit m_extension
->setLocationBarUrl( url
.prettyUrl() );
680 bool KHTMLPart::openUrl( const KUrl
&url
)
682 kDebug( 6050 ) << this << "opening" << url
;
684 d
->m_redirectionTimer
.stop();
686 // check to see if this is an "error://" URL. This is caused when an error
687 // occurs before this part was loaded (e.g. KonqRun), and is passed to
688 // khtmlpart so that it can display the error.
689 if ( url
.protocol() == "error" && url
.hasSubUrl() ) {
692 if( d
->m_bJScriptEnabled
) {
693 d
->m_statusBarText
[BarOverrideText
].clear();
694 d
->m_statusBarText
[BarDefaultText
].clear();
698 * The format of the error url is that two variables are passed in the query:
699 * error = int kio error code, errText = QString error text from kio
700 * and the URL where the error happened is passed as a sub URL.
702 KUrl::List urls
= KUrl::split( url
);
703 //kDebug(6050) << "Handling error URL. URL count:" << urls.count();
705 if ( urls
.count() > 1 ) {
706 KUrl mainURL
= urls
.first();
707 int error
= mainURL
.queryItem( "error" ).toInt();
708 // error=0 isn't a valid error code, so 0 means it's missing from the URL
709 if ( error
== 0 ) error
= KIO::ERR_UNKNOWN
;
710 QString errorText
= mainURL
.queryItem( "errText" );
712 d
->m_workingURL
= KUrl::join( urls
);
713 //kDebug(6050) << "Emitting fixed URL " << d->m_workingURL.prettyUrl();
714 emit d
->m_extension
->setLocationBarUrl( d
->m_workingURL
.prettyUrl() );
715 htmlError( error
, errorText
, d
->m_workingURL
);
720 if (!parentPart()) { // only do it for toplevel part
721 QString host
= url
.isLocalFile() ? "localhost" : url
.host();
722 QString userAgent
= KProtocolManager::userAgentForHost(host
);
723 if (userAgent
!= KProtocolManager::userAgentForHost(QString())) {
724 if (!d
->m_statusBarUALabel
) {
725 d
->m_statusBarUALabel
= new KUrlLabel(d
->m_statusBarExtension
->statusBar());
726 d
->m_statusBarUALabel
->setFixedHeight(KHTMLGlobal::iconLoader()->currentSize(KIconLoader::Small
));
727 d
->m_statusBarUALabel
->setSizePolicy(QSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
));
728 d
->m_statusBarUALabel
->setUseCursor(false);
729 d
->m_statusBarExtension
->addStatusBarItem(d
->m_statusBarUALabel
, 0, false);
730 d
->m_statusBarUALabel
->setPixmap(SmallIcon("preferences-web-browser-identification"));
732 d
->m_statusBarUALabel
->setToolTip(i18n("The fake user-agent '%1' is in use.", userAgent
));
733 } else if (d
->m_statusBarUALabel
) {
734 d
->m_statusBarExtension
->removeStatusBarItem(d
->m_statusBarUALabel
);
735 delete d
->m_statusBarUALabel
;
736 d
->m_statusBarUALabel
= 0L;
740 KParts::BrowserArguments
browserArgs( d
->m_extension
->browserArguments() );
741 KParts::OpenUrlArguments
args( arguments() );
744 // a) we have no frameset (don't test m_frames.count(), iframes get in there)
745 // b) the url is identical with the currently displayed one (except for the htmlref!)
746 // c) the url request is not a POST operation and
747 // d) the caller did not request to reload the page
748 // e) there was no HTTP redirection meanwhile (testcase: webmin's software/tree.cgi)
749 // => we don't reload the whole document and
750 // we just jump to the requested html anchor
751 bool isFrameSet
= false;
752 if ( d
->m_doc
&& d
->m_doc
->isHTMLDocument() ) {
753 HTMLDocumentImpl
* htmlDoc
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
754 isFrameSet
= htmlDoc
->body() && (htmlDoc
->body()->id() == ID_FRAMESET
);
757 if (isFrameSet
&& d
->isLocalAnchorJump(url
) && browserArgs
.softReload
)
759 QList
<khtml::ChildFrame
*>::Iterator it
= d
->m_frames
.begin();
760 const QList
<khtml::ChildFrame
*>::Iterator end
= d
->m_frames
.end();
761 for (; it
!= end
; ++it
) {
762 KHTMLPart
* const part
= qobject_cast
<KHTMLPart
*>( (*it
)->m_part
);
765 // We are reloading frames to make them jump into offsets.
766 KParts::OpenUrlArguments
partargs( part
->arguments() );
767 partargs
.setReload( true );
768 part
->setArguments( partargs
);
770 part
->openUrl( part
->url() );
776 if ( url
.hasRef() && !isFrameSet
)
778 bool noReloadForced
= !args
.reload() && !browserArgs
.redirectedRequest() && !browserArgs
.doPost();
779 if ( noReloadForced
&& d
->isLocalAnchorJump(url
) )
781 kDebug( 6050 ) << "jumping to anchor. m_url = " << url
;
785 if ( !gotoAnchor( url
.encodedHtmlRef()) )
786 gotoAnchor( url
.htmlRef() );
788 d
->m_bComplete
= true;
790 d
->m_doc
->setParsing(false);
792 kDebug( 6050 ) << "completed...";
798 // Save offset of viewport when page is reloaded to be compliant
799 // to every other capable browser out there.
801 args
.setXOffset( d
->m_view
->contentsX() );
802 args
.setYOffset( d
->m_view
->contentsY() );
809 d
->m_restoreScrollPosition
= d
->m_restored
;
810 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
811 connect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
813 // 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
814 // data arrives) (Simon)
815 d
->m_workingURL
= url
;
816 if(url
.protocol().startsWith( "http" ) && !url
.host().isEmpty() &&
817 url
.path().isEmpty()) {
818 d
->m_workingURL
.setPath("/");
819 emit d
->m_extension
->setLocationBarUrl( d
->m_workingURL
.prettyUrl() );
821 setUrl(d
->m_workingURL
);
823 QMap
<QString
,QString
>& metaData
= args
.metaData();
824 metaData
.insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
825 metaData
.insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
826 metaData
.insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
827 metaData
.insert("PropagateHttpHeader", "true");
828 metaData
.insert("ssl_was_in_use", d
->m_ssl_in_use
? "TRUE" : "FALSE" );
829 metaData
.insert("ssl_activate_warnings", "TRUE" );
830 metaData
.insert("cross-domain", toplevelURL().url());
834 metaData
.insert("referrer", d
->m_pageReferrer
);
835 d
->m_cachePolicy
= KIO::CC_Cache
;
837 else if (args
.reload())
838 d
->m_cachePolicy
= KIO::CC_Reload
;
840 d
->m_cachePolicy
= KProtocolManager::cacheControl();
842 if ( browserArgs
.doPost() && (url
.protocol().startsWith("http")) )
844 d
->m_job
= KIO::http_post( url
, browserArgs
.postData
, KIO::HideProgressInfo
);
845 d
->m_job
->addMetaData("content-type", browserArgs
.contentType() );
849 d
->m_job
= KIO::get( url
, KIO::NoReload
, KIO::HideProgressInfo
);
850 d
->m_job
->addMetaData("cache", KIO::getCacheControlString(d
->m_cachePolicy
));
854 d
->m_job
->ui()->setWindow(widget()->topLevelWidget());
855 d
->m_job
->addMetaData(metaData
);
857 connect( d
->m_job
, SIGNAL( result( KJob
* ) ),
858 SLOT( slotFinished( KJob
* ) ) );
859 connect( d
->m_job
, SIGNAL( data( KIO::Job
*, const QByteArray
& ) ),
860 SLOT( slotData( KIO::Job
*, const QByteArray
& ) ) );
861 connect ( d
->m_job
, SIGNAL( infoMessage( KJob
*, const QString
&, const QString
& ) ),
862 SLOT( slotInfoMessage(KJob
*, const QString
& ) ) );
863 connect( d
->m_job
, SIGNAL(redirection(KIO::Job
*, const KUrl
& ) ),
864 SLOT( slotRedirection(KIO::Job
*, const KUrl
&) ) );
866 d
->m_bComplete
= false;
867 d
->m_bLoadEventEmitted
= false;
869 // delete old status bar msg's from kjs (if it _was_ activated on last URL)
870 if( d
->m_bJScriptEnabled
) {
871 d
->m_statusBarText
[BarOverrideText
].clear();
872 d
->m_statusBarText
[BarDefaultText
].clear();
875 // set the javascript flags according to the current url
876 d
->m_bJScriptEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaScriptEnabled(url
.host());
877 setDebugScript( KHTMLGlobal::defaultHTMLSettings()->isJavaScriptDebugEnabled() );
878 d
->m_bJavaEnabled
= KHTMLGlobal::defaultHTMLSettings()->isJavaEnabled(url
.host());
879 d
->m_bPluginsEnabled
= KHTMLGlobal::defaultHTMLSettings()->isPluginsEnabled(url
.host());
882 connect( d
->m_job
, SIGNAL( speed( KJob
*, unsigned long ) ),
883 this, SLOT( slotJobSpeed( KJob
*, unsigned long ) ) );
885 connect( d
->m_job
, SIGNAL( percent( KJob
*, unsigned long ) ),
886 this, SLOT( slotJobPercent( KJob
*, unsigned long ) ) );
888 connect( d
->m_job
, SIGNAL( result( KJob
* ) ),
889 this, SLOT( slotJobDone( KJob
* ) ) );
893 // If this was an explicit reload and the user style sheet should be used,
894 // do a stat to see whether the stylesheet was changed in the meanwhile.
895 if ( args
.reload() && !settings()->userStyleSheet().isEmpty() ) {
896 KUrl
url( settings()->userStyleSheet() );
897 KIO::StatJob
*job
= KIO::stat( url
, KIO::HideProgressInfo
);
898 connect( job
, SIGNAL( result( KJob
* ) ),
899 this, SLOT( slotUserSheetStatDone( KJob
* ) ) );
901 startingJob( d
->m_job
);
907 bool KHTMLPart::closeUrl()
911 KHTMLPageCache::self()->cancelEntry(d
->m_cacheId
);
916 if ( d
->m_doc
&& d
->m_doc
->isHTMLDocument() ) {
917 HTMLDocumentImpl
* hdoc
= static_cast<HTMLDocumentImpl
*>( d
->m_doc
);
919 if ( hdoc
->body() && d
->m_bLoadEventEmitted
) {
920 hdoc
->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT
, false, false );
922 d
->m_doc
->updateRendering();
923 d
->m_bLoadEventEmitted
= false;
927 d
->m_bComplete
= true; // to avoid emitting completed() in slotFinishedParsing() (David)
928 d
->m_bLoadEventEmitted
= true; // don't want that one either
929 d
->m_cachePolicy
= KProtocolManager::cacheControl(); // reset cache policy
931 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
933 KHTMLPageCache::self()->cancelFetch(this);
934 if ( d
->m_doc
&& d
->m_doc
->parsing() )
936 kDebug( 6050 ) << " was still parsing... calling end ";
937 slotFinishedParsing();
938 d
->m_doc
->setParsing(false);
941 if ( !d
->m_workingURL
.isEmpty() )
943 // Aborted before starting to render
944 kDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << url().prettyUrl();
945 emit d
->m_extension
->setLocationBarUrl( url().prettyUrl() );
948 d
->m_workingURL
= KUrl();
950 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
951 khtml::Cache::loader()->cancelRequests( d
->m_doc
->docLoader() );
953 // tell all subframes to stop as well
955 ConstFrameIt it
= d
->m_frames
.constBegin();
956 const ConstFrameIt end
= d
->m_frames
.constEnd();
957 for (; it
!= end
; ++it
)
960 (*it
)->m_run
->abort();
961 if ( !( *it
)->m_part
.isNull() )
962 ( *it
)->m_part
->closeUrl();
965 // tell all objects to stop as well
967 ConstFrameIt it
= d
->m_objects
.constBegin();
968 const ConstFrameIt end
= d
->m_objects
.constEnd();
969 for (; it
!= end
; ++it
)
971 if ( !( *it
)->m_part
.isNull() )
972 ( *it
)->m_part
->closeUrl();
975 // Stop any started redirections as well!! (DA)
976 if ( d
&& d
->m_redirectionTimer
.isActive() )
977 d
->m_redirectionTimer
.stop();
979 // null node activated.
980 emit
nodeActivated(Node());
982 // make sure before clear() runs, we pop out of a dialog's message loop
984 d
->m_view
->closeChildDialogs();
989 DOM::HTMLDocument
KHTMLPart::htmlDocument() const
991 if (d
->m_doc
&& d
->m_doc
->isHTMLDocument())
992 return static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
994 return static_cast<HTMLDocumentImpl
*>(0);
997 DOM::Document
KHTMLPart::document() const
1002 QString
KHTMLPart::documentSource() const
1005 if ( !( url().isLocalFile() ) && KHTMLPageCache::self()->isComplete( d
->m_cacheId
) )
1007 QByteArray sourceArray
;
1008 QDataStream
dataStream( &sourceArray
, QIODevice::WriteOnly
);
1009 KHTMLPageCache::self()->saveData( d
->m_cacheId
, &dataStream
);
1010 QTextStream
stream( sourceArray
, QIODevice::ReadOnly
);
1011 stream
.setCodec( QTextCodec::codecForName( encoding().toLatin1().constData() ) );
1012 sourceStr
= stream
.readAll();
1016 if( KIO::NetAccess::download( url(), tmpFile
, NULL
) )
1019 if ( f
.open( QIODevice::ReadOnly
) )
1021 QTextStream
stream( &f
);
1022 stream
.setCodec( QTextCodec::codecForName( encoding().toLatin1().constData() ) );
1023 sourceStr
= stream
.readAll();
1026 KIO::NetAccess::removeTempFile( tmpFile
);
1034 KParts::BrowserExtension
*KHTMLPart::browserExtension() const
1036 return d
->m_extension
;
1039 KParts::BrowserHostExtension
*KHTMLPart::browserHostExtension() const
1041 return d
->m_hostExtension
;
1044 KHTMLView
*KHTMLPart::view() const
1049 KHTMLViewBar
*KHTMLPart::pTopViewBar() const
1051 if (const_cast<KHTMLPart
*>(this)->parentPart())
1052 return const_cast<KHTMLPart
*>(this)->parentPart()->pTopViewBar();
1053 return d
->m_topViewBar
;
1056 KHTMLViewBar
*KHTMLPart::pBottomViewBar() const
1058 if (const_cast<KHTMLPart
*>(this)->parentPart())
1059 return const_cast<KHTMLPart
*>(this)->parentPart()->pBottomViewBar();
1060 return d
->m_bottomViewBar
;
1063 void KHTMLPart::setStatusMessagesEnabled( bool enable
)
1065 d
->m_statusMessagesEnabled
= enable
;
1068 KJS::Interpreter
*KHTMLPart::jScriptInterpreter()
1070 KJSProxy
*proxy
= jScript();
1071 if (!proxy
|| proxy
->paused())
1074 return proxy
->interpreter();
1077 bool KHTMLPart::statusMessagesEnabled() const
1079 return d
->m_statusMessagesEnabled
;
1082 void KHTMLPart::setJScriptEnabled( bool enable
)
1084 if ( !enable
&& jScriptEnabled() && d
->m_frame
&& d
->m_frame
->m_jscript
) {
1085 d
->m_frame
->m_jscript
->clear();
1087 d
->m_bJScriptForce
= enable
;
1088 d
->m_bJScriptOverride
= true;
1091 bool KHTMLPart::jScriptEnabled() const
1093 if(onlyLocalReferences()) return false;
1095 if ( d
->m_bJScriptOverride
)
1096 return d
->m_bJScriptForce
;
1097 return d
->m_bJScriptEnabled
;
1100 void KHTMLPart::setDNSPrefetch( DNSPrefetch pmode
)
1102 d
->m_bDNSPrefetch
= pmode
;
1103 d
->m_bDNSPrefetchIsDefault
= false;
1106 KHTMLPart::DNSPrefetch
KHTMLPart::dnsPrefetch() const
1108 if (onlyLocalReferences())
1109 return DNSPrefetchDisabled
;
1110 return d
->m_bDNSPrefetch
;
1113 void KHTMLPart::setMetaRefreshEnabled( bool enable
)
1115 d
->m_metaRefreshEnabled
= enable
;
1118 bool KHTMLPart::metaRefreshEnabled() const
1120 return d
->m_metaRefreshEnabled
;
1123 // Define this to disable dlopening kjs_html, when directly linking to it.
1124 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
1125 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
1126 // remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
1127 // Also, change the order of "ecma" and "." in khtml's SUBDIRS line.
1128 // OK - that's the default now, use the opposite of the above instructions to go back
1129 // to "dlopening it" - but it breaks exception catching in kjs_binding.cpp
1130 #define DIRECT_LINKAGE_TO_ECMA
1132 #ifdef DIRECT_LINKAGE_TO_ECMA
1133 extern "C" { KJSProxy
*kjs_html_init(khtml::ChildFrame
* childframe
); }
1136 static bool createJScript(khtml::ChildFrame
*frame
)
1138 #ifndef DIRECT_LINKAGE_TO_ECMA
1139 KLibrary
*lib
= KLibLoader::self()->library(QLatin1String("kjs_html"));
1141 setJScriptEnabled( false );
1144 // look for plain C init function
1145 void *sym
= lib
->symbol("kjs_html_init");
1148 setJScriptEnabled( false );
1151 typedef KJSProxy
* (*initFunction
)(khtml::ChildFrame
*);
1152 initFunction initSym
= (initFunction
) sym
;
1153 frame
->m_jscript
= (*initSym
)(d
->m_frame
);
1154 frame
->m_kjs_lib
= lib
;
1156 frame
->m_jscript
= kjs_html_init(frame
);
1161 KJSProxy
*KHTMLPart::jScript()
1163 if (!jScriptEnabled()) return 0;
1165 if ( !d
->m_frame
) {
1166 KHTMLPart
* p
= parentPart();
1168 d
->m_frame
= new khtml::ChildFrame
;
1169 d
->m_frame
->m_part
= this;
1171 ConstFrameIt it
= p
->d
->m_frames
.constBegin();
1172 const ConstFrameIt end
= p
->d
->m_frames
.constEnd();
1173 for (; it
!= end
; ++it
)
1174 if ((*it
)->m_part
.operator->() == this) {
1182 if ( !d
->m_frame
->m_jscript
)
1183 if (!createJScript(d
->m_frame
))
1185 d
->m_frame
->m_jscript
->setDebugEnabled(d
->m_bJScriptDebugEnabled
);
1187 return d
->m_frame
->m_jscript
;
1190 QVariant
KHTMLPart::crossFrameExecuteScript(const QString
& target
, const QString
& script
)
1192 KHTMLPart
* destpart
= this;
1194 QString trg
= target
.toLower();
1196 if (target
== "_top") {
1197 while (destpart
->parentPart())
1198 destpart
= destpart
->parentPart();
1200 else if (target
== "_parent") {
1202 destpart
= parentPart();
1204 else if (target
== "_self" || target
== "_blank") {
1205 // we always allow these
1208 destpart
= findFrame(target
);
1214 if (destpart
== this)
1215 return executeScript(DOM::Node(), script
);
1217 // now compare the domains
1218 if (destpart
->checkFrameAccess(this))
1219 return destpart
->executeScript(DOM::Node(), script
);
1221 // eww, something went wrong. better execute it in our frame
1222 return executeScript(DOM::Node(), script
);
1225 //Enable this to see all JS scripts being executed
1226 //#define KJS_VERBOSE
1228 KJSErrorDlg
*KHTMLPart::jsErrorExtension() {
1229 if (!d
->m_settings
->jsErrorsEnabled()) {
1234 return parentPart()->jsErrorExtension();
1237 if (!d
->m_statusBarJSErrorLabel
) {
1238 d
->m_statusBarJSErrorLabel
= new KUrlLabel(d
->m_statusBarExtension
->statusBar());
1239 d
->m_statusBarJSErrorLabel
->setFixedHeight(KIconLoader::global()->currentSize(KIconLoader::Small
));
1240 d
->m_statusBarJSErrorLabel
->setSizePolicy(QSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
));
1241 d
->m_statusBarJSErrorLabel
->setUseCursor(false);
1242 d
->m_statusBarExtension
->addStatusBarItem(d
->m_statusBarJSErrorLabel
, 0, false);
1243 d
->m_statusBarJSErrorLabel
->setToolTip(i18n("This web page contains coding errors."));
1244 d
->m_statusBarJSErrorLabel
->setPixmap(SmallIcon("script-error"));
1245 connect(d
->m_statusBarJSErrorLabel
, SIGNAL(leftClickedUrl()), SLOT(launchJSErrorDialog()));
1246 connect(d
->m_statusBarJSErrorLabel
, SIGNAL(rightClickedUrl()), SLOT(jsErrorDialogContextMenu()));
1249 d
->m_jsedlg
= new KJSErrorDlg
;
1250 d
->m_jsedlg
->setURL(url().prettyUrl());
1251 if (KGlobalSettings::showIconsOnPushButtons()) {
1252 d
->m_jsedlg
->_clear
->setIcon(KIcon("edit-clear-locationbar-ltr"));
1253 d
->m_jsedlg
->_close
->setIcon(KIcon("window-close"));
1259 void KHTMLPart::removeJSErrorExtension() {
1261 parentPart()->removeJSErrorExtension();
1264 if (d
->m_statusBarJSErrorLabel
!= 0) {
1265 d
->m_statusBarExtension
->removeStatusBarItem( d
->m_statusBarJSErrorLabel
);
1266 delete d
->m_statusBarJSErrorLabel
;
1267 d
->m_statusBarJSErrorLabel
= 0;
1273 void KHTMLPart::disableJSErrorExtension() {
1274 removeJSErrorExtension();
1275 // These two lines are really kind of hacky, and it sucks to do this inside
1276 // KHTML but I don't know of anything that's reasonably easy as an alternative
1277 // right now. It makes me wonder if there should be a more clean way to
1278 // contact all running "KHTML" instance as opposed to Konqueror instances too.
1279 d
->m_settings
->setJSErrorsEnabled(false);
1280 emit
configurationChanged();
1283 void KHTMLPart::jsErrorDialogContextMenu() {
1284 KMenu
*m
= new KMenu(0L);
1285 m
->addAction(i18n("&Hide Errors"), this, SLOT(removeJSErrorExtension()));
1286 m
->addAction(i18n("&Disable Error Reporting"), this, SLOT(disableJSErrorExtension()));
1287 m
->popup(QCursor::pos());
1290 void KHTMLPart::launchJSErrorDialog() {
1291 KJSErrorDlg
*dlg
= jsErrorExtension();
1298 void KHTMLPart::launchJSConfigDialog() {
1300 args
<< "khtml_java_js";
1301 KToolInvocation::kdeinitExec( "kcmshell4", args
);
1304 QVariant
KHTMLPart::executeScript(const QString
& filename
, int baseLine
, const DOM::Node
& n
, const QString
& script
)
1307 // The script is now printed by KJS's Parser::parse
1308 kDebug(6070) << "executeScript: caller='" << objectName() << "' filename=" << filename
<< " baseLine=" << baseLine
/*<< " script=" << script*/;
1310 KJSProxy
*proxy
= jScript();
1312 if (!proxy
|| proxy
->paused())
1315 //Make sure to initialize the interpreter before creating Completion
1316 (void)proxy
->interpreter();
1318 KJS::Completion comp
;
1320 QVariant ret
= proxy
->evaluate(filename
, baseLine
, script
, n
, &comp
);
1325 if (comp
.complType() == KJS::Throw
&& comp
.value()) {
1326 KJSErrorDlg
*dlg
= jsErrorExtension();
1328 QString msg
= KJSDebugger::DebugWindow::exceptionToString(
1329 proxy
->interpreter()->globalExec(), comp
.value());
1330 dlg
->addError(i18n("<qt><b>Error</b>: %1: %2</qt>",
1331 Qt::escape(filename
), Qt::escape(msg
)));
1335 // Handle immediate redirects now (e.g. location='foo')
1336 if ( !d
->m_redirectURL
.isEmpty() && d
->m_delayRedirect
== -1 )
1338 kDebug(6070) << "executeScript done, handling immediate redirection NOW";
1339 // Must abort tokenizer, no further script must execute.
1340 khtml::Tokenizer
* t
= d
->m_doc
->tokenizer();
1343 d
->m_redirectionTimer
.setSingleShot( true );
1344 d
->m_redirectionTimer
.start( 0 );
1350 QVariant
KHTMLPart::executeScript( const QString
&script
)
1352 return executeScript( DOM::Node(), script
);
1355 QVariant
KHTMLPart::executeScript( const DOM::Node
&n
, const QString
&script
)
1358 kDebug(6070) << "caller=" << objectName() << "node=" << n
.nodeName().string().toLatin1().constData() << "(" << (n
.isNull() ? 0 : n
.nodeType()) << ") " /* << script */;
1360 KJSProxy
*proxy
= jScript();
1362 if (!proxy
|| proxy
->paused())
1364 (void)proxy
->interpreter();//Make sure stuff is initialized
1366 ++(d
->m_runningScripts
);
1367 KJS::Completion comp
;
1368 const QVariant ret
= proxy
->evaluate( QString(), 1, script
, n
, &comp
);
1369 --(d
->m_runningScripts
);
1374 if (comp
.complType() == KJS::Throw
&& comp
.value()) {
1375 KJSErrorDlg
*dlg
= jsErrorExtension();
1377 QString msg
= KJSDebugger::DebugWindow::exceptionToString(
1378 proxy
->interpreter()->globalExec(), comp
.value());
1379 dlg
->addError(i18n("<qt><b>Error</b>: node %1: %2</qt>",
1380 n
.nodeName().string(), Qt::escape(msg
)));
1384 if (!d
->m_runningScripts
&& d
->m_doc
&& !d
->m_doc
->parsing() && d
->m_submitForm
)
1388 kDebug(6070) << "done";
1393 void KHTMLPart::setJavaEnabled( bool enable
)
1395 d
->m_bJavaForce
= enable
;
1396 d
->m_bJavaOverride
= true;
1399 bool KHTMLPart::javaEnabled() const
1401 if (onlyLocalReferences()) return false;
1404 if( d
->m_bJavaOverride
)
1405 return d
->m_bJavaForce
;
1406 return d
->m_bJavaEnabled
;
1412 void KHTMLPart::setPluginsEnabled( bool enable
)
1414 d
->m_bPluginsForce
= enable
;
1415 d
->m_bPluginsOverride
= true;
1418 bool KHTMLPart::pluginsEnabled() const
1420 if (onlyLocalReferences()) return false;
1422 if ( d
->m_bPluginsOverride
)
1423 return d
->m_bPluginsForce
;
1424 return d
->m_bPluginsEnabled
;
1427 static int s_DOMTreeIndentLevel
= 0;
1429 void KHTMLPart::slotDebugDOMTree()
1432 qDebug("%s", d
->m_doc
->toString().string().toLatin1().constData());
1434 // Now print the contents of the frames that contain HTML
1436 const int indentLevel
= s_DOMTreeIndentLevel
++;
1438 ConstFrameIt it
= d
->m_frames
.constBegin();
1439 const ConstFrameIt end
= d
->m_frames
.constEnd();
1440 for (; it
!= end
; ++it
)
1441 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
1442 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
1443 kDebug(6050) << QString().leftJustified(s_DOMTreeIndentLevel
*4,' ') << "FRAME " << p
->objectName() << " ";
1444 static_cast<KHTMLPart
*>( p
)->slotDebugDOMTree();
1446 s_DOMTreeIndentLevel
= indentLevel
;
1449 void KHTMLPart::slotDebugScript()
1452 jScript()->showDebugWindow();
1455 void KHTMLPart::slotDebugRenderTree()
1459 d
->m_doc
->renderer()->printTree();
1460 // dump out the contents of the rendering & DOM trees
1462 // QTextStream outputStream(dumps,QIODevice::WriteOnly);
1463 // d->m_doc->renderer()->layer()->dump( outputStream );
1464 // kDebug() << "dump output:" << "\n" + dumps;
1469 void KHTMLPart::slotStopAnimations()
1474 void KHTMLPart::setAutoloadImages( bool enable
)
1476 if ( d
->m_doc
&& d
->m_doc
->docLoader()->autoloadImages() == enable
)
1480 d
->m_doc
->docLoader()->setAutoloadImages( enable
);
1482 unplugActionList( "loadImages" );
1485 delete d
->m_paLoadImages
;
1486 d
->m_paLoadImages
= 0;
1488 else if ( !d
->m_paLoadImages
) {
1489 d
->m_paLoadImages
= new KAction( i18n( "Display Images on Page" ), this );
1490 actionCollection()->addAction( "loadImages", d
->m_paLoadImages
);
1491 d
->m_paLoadImages
->setIcon( KIcon( "image-loading" ) );
1492 connect( d
->m_paLoadImages
, SIGNAL( triggered( bool ) ), this, SLOT( slotLoadImages() ) );
1495 if ( d
->m_paLoadImages
) {
1496 QList
<QAction
*> lst
;
1497 lst
.append( d
->m_paLoadImages
);
1498 plugActionList( "loadImages", lst
);
1502 bool KHTMLPart::autoloadImages() const
1505 return d
->m_doc
->docLoader()->autoloadImages();
1510 void KHTMLPart::clear()
1512 if ( d
->m_bCleared
)
1515 d
->m_bCleared
= true;
1517 d
->m_bClearing
= true;
1520 ConstFrameIt it
= d
->m_frames
.constBegin();
1521 const ConstFrameIt end
= d
->m_frames
.constEnd();
1522 for(; it
!= end
; ++it
)
1524 // Stop HTMLRun jobs for frames
1526 (*it
)->m_run
->abort();
1531 ConstFrameIt it
= d
->m_objects
.constBegin();
1532 const ConstFrameIt end
= d
->m_objects
.constEnd();
1533 for(; it
!= end
; ++it
)
1535 // Stop HTMLRun jobs for objects
1537 (*it
)->m_run
->abort();
1542 findTextBegin(); // resets d->m_findNode and d->m_findPos
1543 d
->m_mousePressNode
= DOM::Node();
1548 if (d
->m_doc
->attached()) //the view may have detached it already
1552 // Moving past doc so that onUnload works.
1553 if ( d
->m_frame
&& d
->m_frame
->m_jscript
)
1554 d
->m_frame
->m_jscript
->clear();
1556 // stopping marquees
1557 if (d
->m_doc
&& d
->m_doc
->renderer() && d
->m_doc
->renderer()->layer())
1558 d
->m_doc
->renderer()->layer()->suspendMarquees();
1563 // do not dereference the document before the jscript and view are cleared, as some destructors
1564 // might still try to access the document.
1570 delete d
->m_decoder
;
1573 // We don't want to change between parts if we are going to delete all of them anyway
1574 disconnect( partManager(), SIGNAL( activePartChanged( KParts::Part
* ) ),
1575 this, SLOT( slotActiveFrameChanged( KParts::Part
* ) ) );
1577 if (d
->m_frames
.count())
1579 const KHTMLFrameList frames
= d
->m_frames
;
1580 d
->m_frames
.clear();
1581 ConstFrameIt it
= frames
.begin();
1582 const ConstFrameIt end
= frames
.end();
1583 for(; it
!= end
; ++it
)
1585 if ( (*it
)->m_part
)
1587 partManager()->removePart( (*it
)->m_part
);
1588 delete (KParts::ReadOnlyPart
*)(*it
)->m_part
;
1593 d
->m_suppressedPopupOriginParts
.clear();
1595 if (d
->m_objects
.count())
1597 KHTMLFrameList objects
= d
->m_objects
;
1598 d
->m_objects
.clear();
1599 ConstFrameIt oi
= objects
.constBegin();
1600 const ConstFrameIt oiEnd
= objects
.constEnd();
1602 for (; oi
!= oiEnd
; ++oi
)
1604 if ( (*oi
)->m_part
)
1605 delete (KParts::ReadOnlyPart
*)(*oi
)->m_part
;
1610 // Listen to part changes again
1611 connect( partManager(), SIGNAL( activePartChanged( KParts::Part
* ) ),
1612 this, SLOT( slotActiveFrameChanged( KParts::Part
* ) ) );
1614 d
->clearRedirection();
1615 d
->m_redirectLockHistory
= true;
1616 d
->m_bClearing
= false;
1617 d
->m_frameNameId
= 1;
1618 d
->m_bFirstData
= true;
1620 d
->m_bMousePressed
= false;
1622 if (d
->editor_context
.m_caretBlinkTimer
>= 0)
1623 killTimer(d
->editor_context
.m_caretBlinkTimer
);
1624 d
->editor_context
.reset();
1625 #ifndef QT_NO_CLIPBOARD
1626 connect( qApp
->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
1629 d
->m_jobPercent
= 0;
1631 if ( !d
->m_haveEncoding
)
1632 d
->m_encoding
.clear();
1634 d
->m_DNSPrefetchQueue
.clear();
1635 if (d
->m_DNSPrefetchTimer
> 0)
1636 killTimer(d
->m_DNSPrefetchTimer
);
1637 d
->m_DNSPrefetchTimer
= -1;
1638 d
->m_lookedupHosts
.clear();
1639 if (d
->m_DNSTTLTimer
> 0)
1640 killTimer(d
->m_DNSTTLTimer
);
1641 d
->m_DNSTTLTimer
= -1;
1642 d
->m_numDNSPrefetchedNames
= 0;
1645 d
->m_parsetime
.restart();
1649 bool KHTMLPart::openFile()
1654 DOM::HTMLDocumentImpl
*KHTMLPart::docImpl() const
1656 if ( d
&& d
->m_doc
&& d
->m_doc
->isHTMLDocument() )
1657 return static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
1661 DOM::DocumentImpl
*KHTMLPart::xmlDocImpl() const
1668 void KHTMLPart::slotInfoMessage(KJob
* kio_job
, const QString
& msg
)
1670 assert(d
->m_job
== kio_job
);
1673 setStatusBarText(msg
, BarDefaultText
);
1676 void KHTMLPart::setPageSecurity( PageSecurity sec
)
1678 emit d
->m_extension
->setPageSecurity( sec
);
1681 void KHTMLPart::slotData( KIO::Job
* kio_job
, const QByteArray
&data
)
1683 assert ( d
->m_job
== kio_job
);
1685 //kDebug( 6050 ) << "slotData: " << data.size();
1687 if ( !d
->m_workingURL
.isEmpty() )
1689 //kDebug( 6050 ) << "begin!";
1691 // We must suspend KIO while we're inside begin() because it can cause
1692 // crashes if a window (such as kjsdebugger) goes back into the event loop,
1693 // more data arrives, and begin() gets called again (re-entered).
1694 d
->m_job
->suspend();
1695 begin( d
->m_workingURL
, arguments().xOffset(), arguments().yOffset() );
1698 if (d
->m_cachePolicy
== KIO::CC_Refresh
)
1699 d
->m_doc
->docLoader()->setCachePolicy(KIO::CC_Verify
);
1701 d
->m_doc
->docLoader()->setCachePolicy(d
->m_cachePolicy
);
1703 d
->m_workingURL
= KUrl();
1705 d
->m_cacheId
= KHTMLPageCache::self()->createCacheEntry();
1707 // When the first data arrives, the metadata has just been made available
1708 d
->m_httpHeaders
= d
->m_job
->queryMetaData("HTTP-Headers");
1709 time_t cacheCreationDate
= d
->m_job
->queryMetaData("cache-creation-date").toLong();
1710 d
->m_doc
->docLoader()->setCacheCreationDate(cacheCreationDate
);
1712 d
->m_pageServices
= d
->m_job
->queryMetaData("PageServices");
1713 d
->m_pageReferrer
= d
->m_job
->queryMetaData("referrer");
1714 d
->m_ssl_in_use
= (d
->m_job
->queryMetaData("ssl_in_use") == "TRUE");
1717 KHTMLPart
*p
= parentPart();
1718 if (p
&& p
->d
->m_ssl_in_use
!= d
->m_ssl_in_use
) {
1719 while (p
->parentPart()) p
= p
->parentPart();
1721 p
->setPageSecurity( NotCrypted
);
1725 setPageSecurity( d
->m_ssl_in_use
? Encrypted
: NotCrypted
);
1727 // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
1728 d
->m_ssl_parent_ip
= d
->m_job
->queryMetaData("ssl_parent_ip");
1729 d
->m_ssl_parent_cert
= d
->m_job
->queryMetaData("ssl_parent_cert");
1730 d
->m_ssl_peer_chain
= d
->m_job
->queryMetaData("ssl_peer_chain");
1731 d
->m_ssl_peer_ip
= d
->m_job
->queryMetaData("ssl_peer_ip");
1732 d
->m_ssl_cipher
= d
->m_job
->queryMetaData("ssl_cipher");
1733 d
->m_ssl_protocol_version
= d
->m_job
->queryMetaData("ssl_protocol_version");
1734 d
->m_ssl_cipher_used_bits
= d
->m_job
->queryMetaData("ssl_cipher_used_bits");
1735 d
->m_ssl_cipher_bits
= d
->m_job
->queryMetaData("ssl_cipher_bits");
1736 d
->m_ssl_cert_errors
= d
->m_job
->queryMetaData("ssl_cert_errors");
1738 // Check for charset meta-data
1739 QString qData
= d
->m_job
->queryMetaData("charset");
1740 if ( !qData
.isEmpty() && !d
->m_haveEncoding
) // only use information if the user didn't override the settings
1741 d
->m_encoding
= qData
;
1744 // Support for http-refresh
1745 qData
= d
->m_job
->queryMetaData("http-refresh");
1746 if( !qData
.isEmpty())
1747 d
->m_doc
->processHttpEquiv("refresh", qData
);
1749 // DISABLED: Support Content-Location per section 14.14 of RFC 2616.
1750 // See BR# 51185,BR# 82747
1752 QString baseURL = d->m_job->queryMetaData ("content-location");
1753 if (!baseURL.isEmpty())
1754 d->m_doc->setBaseURL(KUrl( d->m_doc->completeURL(baseURL) ));
1757 // Support for Content-Language
1758 QString language
= d
->m_job
->queryMetaData("content-language");
1759 if (!language
.isEmpty())
1760 d
->m_doc
->setContentLanguage(language
);
1762 if ( !url().isLocalFile() )
1764 // Support for http last-modified
1765 d
->m_lastModified
= d
->m_job
->queryMetaData("modified");
1768 d
->m_lastModified
.clear(); // done on-demand by lastModified()
1771 KHTMLPageCache::self()->addData(d
->m_cacheId
, data
);
1772 write( data
.data(), data
.size() );
1774 if (d
->m_frame
&& d
->m_frame
->m_jscript
)
1775 d
->m_frame
->m_jscript
->dataReceived();
1779 void KHTMLPart::slotRestoreData(const QByteArray
&data
)
1782 if ( !d
->m_workingURL
.isEmpty() )
1784 long saveCacheId
= d
->m_cacheId
;
1785 QString savePageReferrer
= d
->m_pageReferrer
;
1786 QString saveEncoding
= d
->m_encoding
;
1787 begin( d
->m_workingURL
, arguments().xOffset(), arguments().yOffset() );
1788 d
->m_encoding
= saveEncoding
;
1789 d
->m_pageReferrer
= savePageReferrer
;
1790 d
->m_cacheId
= saveCacheId
;
1791 d
->m_workingURL
= KUrl();
1794 //kDebug( 6050 ) << data.size();
1795 write( data
.data(), data
.size() );
1797 if (data
.size() == 0)
1799 //kDebug( 6050 ) << "<<end of data>>";
1801 if (d
->m_doc
&& d
->m_doc
->parsing())
1802 end(); //will emit completed()
1806 void KHTMLPart::showError( KJob
* job
)
1808 kDebug(6050) << "d->m_bParsing=" << (d
->m_doc
&& d
->m_doc
->parsing()) << " d->m_bComplete=" << d
->m_bComplete
1809 << " d->m_bCleared=" << d
->m_bCleared
;
1811 if (job
->error() == KIO::ERR_NO_CONTENT
)
1814 if ( (d
->m_doc
&& d
->m_doc
->parsing()) || d
->m_workingURL
.isEmpty() ) // if we got any data already
1815 job
->uiDelegate()->showErrorMessage();
1818 htmlError( job
->error(), job
->errorText(), d
->m_workingURL
);
1822 // This is a protected method, placed here because of it's relevance to showError
1823 void KHTMLPart::htmlError( int errorCode
, const QString
& text
, const KUrl
& reqUrl
)
1825 kDebug(6050) << "errorCode" << errorCode
<< "text" << text
;
1826 // make sure we're not executing any embedded JS
1827 bool bJSFO
= d
->m_bJScriptForce
;
1828 bool bJSOO
= d
->m_bJScriptOverride
;
1829 d
->m_bJScriptForce
= false;
1830 d
->m_bJScriptOverride
= true;
1833 QString errorName
, techName
, description
;
1834 QStringList causes
, solutions
;
1836 QByteArray raw
= KIO::rawErrorDetail( errorCode
, text
, &reqUrl
);
1837 QDataStream
stream(raw
);
1839 stream
>> errorName
>> techName
>> description
>> causes
>> solutions
;
1841 QString url
, protocol
, datetime
;
1842 url
= Qt::escape( reqUrl
.prettyUrl() );
1843 protocol
= reqUrl
.protocol();
1844 datetime
= KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
1845 KLocale::LongDate
);
1847 QString
filename( KStandardDirs::locate( "data", "khtml/error.html" ) );
1848 QFile
file( filename
);
1849 bool isOpened
= file
.open( QIODevice::ReadOnly
);
1851 kWarning(6050) << "Could not open error html template:" << filename
;
1853 QString html
= QString( QLatin1String( file
.readAll() ) );
1855 html
.replace( QLatin1String( "TITLE" ), i18n( "Error: %1 - %2", errorName
, url
) );
1856 html
.replace( QLatin1String( "DIRECTION" ), QApplication::isRightToLeft() ? "rtl" : "ltr" );
1857 html
.replace( QLatin1String( "ICON_PATH" ), KIconLoader::global()->iconPath( "dialog-warning", -KIconLoader::SizeHuge
) );
1859 QString doc
= QLatin1String( "<h1>" );
1860 doc
+= i18n( "The requested operation could not be completed" );
1861 doc
+= QLatin1String( "</h1><h2>" );
1863 doc
+= QLatin1String( "</h2>" );
1864 if ( !techName
.isNull() ) {
1865 doc
+= QLatin1String( "<h2>" );
1866 doc
+= i18n( "Technical Reason: " );
1868 doc
+= QLatin1String( "</h2>" );
1870 doc
+= QLatin1String( "<h3>" );
1871 doc
+= i18n( "Details of the Request:" );
1872 doc
+= QLatin1String( "</h3><ul><li>" );
1873 doc
+= i18n( "URL: %1" , url
);
1874 doc
+= QLatin1String( "</li><li>" );
1875 if ( !protocol
.isNull() ) {
1876 doc
+= i18n( "Protocol: %1", protocol
);
1877 doc
+= QLatin1String( "</li><li>" );
1879 doc
+= i18n( "Date and Time: %1" , datetime
);
1880 doc
+= QLatin1String( "</li><li>" );
1881 doc
+= i18n( "Additional Information: %1" , text
);
1882 doc
+= QLatin1String( "</li></ul><h3>" );
1883 doc
+= i18n( "Description:" );
1884 doc
+= QLatin1String( "</h3><p>" );
1886 doc
+= QLatin1String( "</p>" );
1887 if ( causes
.count() ) {
1888 doc
+= QLatin1String( "<h3>" );
1889 doc
+= i18n( "Possible Causes:" );
1890 doc
+= QLatin1String( "</h3><ul><li>" );
1891 doc
+= causes
.join( "</li><li>" );
1892 doc
+= QLatin1String( "</li></ul>" );
1894 if ( solutions
.count() ) {
1895 doc
+= QLatin1String( "<h3>" );
1896 doc
+= i18n( "Possible Solutions:" );
1897 doc
+= QLatin1String( "</h3><ul><li>" );
1898 doc
+= solutions
.join( "</li><li>" );
1899 doc
+= QLatin1String( "</li></ul>" );
1902 html
.replace( QLatin1String("TEXT"), doc
);
1907 d
->m_bJScriptForce
= bJSFO
;
1908 d
->m_bJScriptOverride
= bJSOO
;
1910 // make the working url the current url, so that reload works and
1911 // emit the progress signals to advance one step in the history
1912 // (so that 'back' works)
1913 setUrl(reqUrl
); // same as d->m_workingURL
1914 d
->m_workingURL
= KUrl();
1919 void KHTMLPart::slotFinished( KJob
* job
)
1926 KHTMLPageCache::self()->cancelEntry(d
->m_cacheId
);
1928 // The following catches errors that occur as a result of HTTP
1929 // to FTP redirections where the FTP URL is a directory. Since
1930 // KIO cannot change a redirection request from GET to LISTDIR,
1931 // we have to take care of it here once we know for sure it is
1933 if (job
->error() == KIO::ERR_IS_DIRECTORY
)
1935 emit
canceled( job
->errorString() );
1936 emit d
->m_extension
->openUrlRequest( d
->m_workingURL
);
1940 emit
canceled( job
->errorString() );
1941 // TODO: what else ?
1948 KIO::TransferJob
*tjob
= ::qobject_cast
<KIO::TransferJob
*>(job
);
1949 if (tjob
&& tjob
->isErrorPage()) {
1950 HTMLPartContainerElementImpl
*elt
= d
->m_frame
?
1951 (HTMLPartContainerElementImpl
*)d
->m_frame
->m_partContainerElement
: 0;
1956 elt
->partLoadingErrorNotify();
1958 if (d
->m_bComplete
) return;
1961 //kDebug( 6050 ) << "slotFinished";
1963 KHTMLPageCache::self()->endData(d
->m_cacheId
);
1964 if (d
->m_frame
&& d
->m_frame
->m_jscript
)
1965 d
->m_frame
->m_jscript
->dataReceived();
1967 if ( d
->m_doc
&& d
->m_doc
->docLoader()->expireDate() && url().protocol().toLower().startsWith("http"))
1968 KIO::http_update_cache(url(), false, d
->m_doc
->docLoader()->expireDate());
1970 d
->m_workingURL
= KUrl();
1972 if ( d
->m_doc
&& d
->m_doc
->parsing())
1973 end(); //will emit completed()
1976 void KHTMLPart::begin( const KUrl
&url
, int xOffset
, int yOffset
)
1978 // No need to show this for a new page until an error is triggered
1979 if (!parentPart()) {
1980 removeJSErrorExtension();
1981 setSuppressedPopupIndicator( false );
1982 d
->m_openableSuppressedPopups
= 0;
1983 foreach ( KHTMLPart
* part
, d
->m_suppressedPopupOriginParts
) {
1985 KJS::Window
*w
= KJS::Window::retrieveWindow( part
);
1987 w
->forgetSuppressedWindows();
1992 d
->m_bCleared
= false;
1994 d
->m_bComplete
= false;
1995 d
->m_bLoadEventEmitted
= false;
1997 d
->m_bCleared
= false;
2000 QString urlString
= url
.url();
2001 KHTMLGlobal::vLinks()->insert( urlString
);
2002 QString urlString2
= url
.prettyUrl();
2003 if ( urlString
!= urlString2
) {
2004 KHTMLGlobal::vLinks()->insert( urlString2
);
2011 KParts::OpenUrlArguments args
= arguments();
2012 args
.setXOffset(xOffset
);
2013 args
.setYOffset(yOffset
);
2016 d
->m_pageReferrer
.clear();
2019 d
->m_referrer
= ref
.protocol().startsWith("http") ? ref
.url() : "";
2023 bool servedAsXHTML
= args
.mimeType() == "application/xhtml+xml";
2024 bool servedAsSVG
= !servedAsXHTML
&& args
.mimeType() == "image/svg+xml";
2025 KMimeType::Ptr mime
= KMimeType::mimeType( args
.mimeType(), KMimeType::ResolveAliases
);
2026 // We want to make sure text/xml and application/xml are both handled right...
2027 bool servedAsXML
= mime
&& mime
->is( "text/xml" );
2028 // ### not sure if XHTML documents served as text/xml should use DocumentImpl or HTMLDocumentImpl
2029 if ( servedAsSVG
) {
2030 d
->m_doc
= DOMImplementationImpl::instance()->createSVGDocument( d
->m_view
);
2032 if ( servedAsXML
&& !servedAsXHTML
) { // any XML derivative, except XHTML
2033 d
->m_doc
= DOMImplementationImpl::instance()->createXMLDocument( d
->m_view
);
2035 d
->m_doc
= DOMImplementationImpl::instance()->createHTMLDocument( d
->m_view
);
2036 // HTML or XHTML? (#86446)
2037 static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->setHTMLRequested( !servedAsXHTML
);
2042 d
->m_doc
->setURL( url
.url() );
2044 if (!d
->m_doc
->attached())
2045 d
->m_doc
->attach( );
2046 d
->m_doc
->setBaseURL( KUrl() );
2047 d
->m_doc
->docLoader()->setShowAnimations( KHTMLGlobal::defaultHTMLSettings()->showAnimations() );
2050 d
->m_paUseStylesheet
->setItems(QStringList());
2051 d
->m_paUseStylesheet
->setEnabled( false );
2053 setAutoloadImages( KHTMLGlobal::defaultHTMLSettings()->autoLoadImages() );
2054 QString userStyleSheet
= KHTMLGlobal::defaultHTMLSettings()->userStyleSheet();
2055 if ( !userStyleSheet
.isEmpty() )
2056 setUserStyleSheet( KUrl( userStyleSheet
) );
2058 d
->m_doc
->setRestoreState(d
->m_extension
->browserArguments().docState
);
2059 connect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2061 emit d
->m_extension
->enableAction( "print", true );
2063 d
->m_doc
->setParsing(true);
2066 void KHTMLPart::write( const char *data
, int len
)
2068 if ( !d
->m_decoder
)
2069 d
->m_decoder
= createDecoder();
2072 len
= strlen( data
);
2077 QString decoded
=d
->m_decoder
->decodeWithBuffering(data
,len
);
2079 if(decoded
.isEmpty())
2085 khtml::Tokenizer
* t
= d
->m_doc
->tokenizer();
2087 t
->write( decoded
, true );
2091 void KHTMLPart::setAlwaysHonourDoctype( bool b
)
2093 d
->m_bStrictModeQuirk
= !b
;
2096 void KHTMLPart::write( const QString
&str
)
2101 if(d
->m_bFirstData
) {
2102 // determine the parse mode
2103 if (d
->m_bStrictModeQuirk
) {
2104 d
->m_doc
->setParseMode( DocumentImpl::Strict
);
2105 d
->m_bFirstData
= false;
2110 khtml::Tokenizer
* t
= d
->m_doc
->tokenizer();
2112 t
->write( str
, true );
2115 void KHTMLPart::end()
2120 QString decoded
=d
->m_decoder
->flush();
2121 if (d
->m_bFirstData
)
2123 if (!decoded
.isEmpty())
2126 d
->m_doc
->finishParsing();
2130 void KHTMLPart::onFirstData()
2132 assert( d
->m_bFirstData
);
2134 // determine the parse mode
2135 d
->m_doc
->determineParseMode();
2136 d
->m_bFirstData
= false;
2138 // ### this is still quite hacky, but should work a lot better than the old solution
2139 if (d
->m_decoder
->visuallyOrdered())
2140 d
->m_doc
->setVisuallyOrdered();
2141 d
->m_doc
->recalcStyle( NodeImpl::Force
);
2144 bool KHTMLPart::doOpenStream( const QString
& mimeType
)
2146 KMimeType::Ptr mime
= KMimeType::mimeType(mimeType
, KMimeType::ResolveAliases
);
2147 if ( mime
&& ( mime
->is( "text/html" ) || mime
->is( "text/xml" ) ) )
2155 bool KHTMLPart::doWriteStream( const QByteArray
& data
)
2157 write( data
.data(), data
.size() );
2161 bool KHTMLPart::doCloseStream()
2168 void KHTMLPart::paint(QPainter
*p
, const QRect
&rc
, int yOff
, bool *more
)
2170 if (!d
->m_view
) return;
2171 d
->m_view
->paint(p
, rc
, yOff
, more
);
2174 void KHTMLPart::stopAnimations()
2177 d
->m_doc
->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled
);
2179 ConstFrameIt it
= d
->m_frames
.constBegin();
2180 const ConstFrameIt end
= d
->m_frames
.constEnd();
2181 for (; it
!= end
; ++it
)
2182 if ( !(*it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
2183 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
2184 static_cast<KHTMLPart
*>( p
)->stopAnimations();
2188 void KHTMLPart::resetFromScript()
2191 d
->m_bComplete
= false;
2192 d
->m_bLoadEventEmitted
= false;
2193 disconnect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2194 connect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2195 d
->m_doc
->setParsing(true);
2200 void KHTMLPart::slotFinishedParsing()
2202 d
->m_doc
->setParsing(false);
2203 d
->m_doc
->dispatchWindowEvent(EventImpl::KHTML_CONTENTLOADED_EVENT
, false, false);
2204 checkEmitLoadEvent();
2205 disconnect(d
->m_doc
,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
2208 return; // We are probably being destructed.
2213 void KHTMLPart::slotLoaderRequestStarted( 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_totalObjectCount
);
2220 p
= p
->parentPart();
2221 if ( !p
&& op
->d
->m_loadedObjects
<= op
->d
->m_totalObjectCount
2222 && !op
->d
->m_progressUpdateTimer
.isActive()) {
2223 op
->d
->m_progressUpdateTimer
.setSingleShot( true );
2224 op
->d
->m_progressUpdateTimer
.start( 200 );
2230 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader
* dl
, khtml::CachedObject
*obj
)
2232 if ( obj
&& obj
->type() == khtml::CachedObject::Image
&& d
->m_doc
&& d
->m_doc
->docLoader() == dl
) {
2233 KHTMLPart
* p
= this;
2235 KHTMLPart
* const op
= p
;
2236 ++(p
->d
->m_loadedObjects
);
2237 p
= p
->parentPart();
2238 if ( !p
&& op
->d
->m_loadedObjects
<= op
->d
->m_totalObjectCount
&& op
->d
->m_jobPercent
<= 100
2239 && !op
->d
->m_progressUpdateTimer
.isActive()) {
2240 op
->d
->m_progressUpdateTimer
.setSingleShot( true );
2241 op
->d
->m_progressUpdateTimer
.start( 200 );
2249 void KHTMLPart::slotProgressUpdate()
2252 if ( d
->m_loadedObjects
< d
->m_totalObjectCount
)
2253 percent
= d
->m_jobPercent
/ 4 + ( d
->m_loadedObjects
*300 ) / ( 4*d
->m_totalObjectCount
);
2255 percent
= d
->m_jobPercent
;
2257 if( d
->m_bComplete
)
2260 if (d
->m_statusMessagesEnabled
) {
2261 if( d
->m_bComplete
)
2262 emit d
->m_extension
->infoMessage( i18n( "Page loaded." ));
2263 else if ( d
->m_loadedObjects
< d
->m_totalObjectCount
&& percent
>= 75 )
2264 emit d
->m_extension
->infoMessage( i18np( "%1 Image of %2 loaded.", "%1 Images of %2 loaded.", d
->m_loadedObjects
, d
->m_totalObjectCount
) );
2267 emit d
->m_extension
->loadingProgress( percent
);
2270 void KHTMLPart::slotJobSpeed( KJob
* /*job*/, unsigned long speed
)
2272 d
->m_jobspeed
= speed
;
2274 setStatusBarText(jsStatusBarText(), BarOverrideText
);
2277 void KHTMLPart::slotJobPercent( KJob
* /*job*/, unsigned long percent
)
2279 d
->m_jobPercent
= percent
;
2281 if ( !parentPart() ) {
2282 d
->m_progressUpdateTimer
.setSingleShot( true );
2283 d
->m_progressUpdateTimer
.start( 0 );
2287 void KHTMLPart::slotJobDone( KJob
* /*job*/ )
2289 d
->m_jobPercent
= 100;
2291 if ( !parentPart() ) {
2292 d
->m_progressUpdateTimer
.setSingleShot( true );
2293 d
->m_progressUpdateTimer
.start( 0 );
2297 void KHTMLPart::slotUserSheetStatDone( KJob
*_job
)
2299 using namespace KIO
;
2301 if ( _job
->error() ) {
2306 const UDSEntry entry
= dynamic_cast<KIO::StatJob
*>( _job
)->statResult();
2307 const time_t lastModified
= entry
.numberValue( KIO::UDSEntry::UDS_MODIFICATION_TIME
, -1 );
2309 // If the filesystem supports modification times, only reload the
2310 // user-defined stylesheet if necessary - otherwise always reload.
2311 if ( lastModified
!= static_cast<time_t>(-1) ) {
2312 if ( d
->m_userStyleSheetLastModified
>= lastModified
) {
2315 d
->m_userStyleSheetLastModified
= lastModified
;
2318 setUserStyleSheet( KUrl( settings()->userStyleSheet() ) );
2321 void KHTMLPart::checkCompleted()
2323 // kDebug( 6050 ) << this << name();
2324 // kDebug( 6050 ) << " parsing: " << (d->m_doc && d->m_doc->parsing());
2325 // kDebug( 6050 ) << " complete: " << d->m_bComplete;
2327 // restore the cursor position
2328 if (d
->m_doc
&& !d
->m_doc
->parsing() && !d
->m_focusNodeRestored
)
2330 if (d
->m_focusNodeNumber
>= 0)
2331 d
->m_doc
->setFocusNode(d
->m_doc
->nodeWithAbsIndex(d
->m_focusNodeNumber
));
2333 d
->m_focusNodeRestored
= true;
2336 bool bPendingChildRedirection
= false;
2337 // Any frame that hasn't completed yet ?
2338 ConstFrameIt it
= d
->m_frames
.constBegin();
2339 const ConstFrameIt end
= d
->m_frames
.constEnd();
2340 for (; it
!= end
; ++it
) {
2341 if ( !(*it
)->m_bCompleted
)
2343 //kDebug( 6050 ) << this << " is waiting for " << (*it)->m_part;
2346 // Check for frames with pending redirections
2347 if ( (*it
)->m_bPendingRedirection
)
2348 bPendingChildRedirection
= true;
2351 // Any object that hasn't completed yet ?
2353 ConstFrameIt oi
= d
->m_objects
.constBegin();
2354 const ConstFrameIt oiEnd
= d
->m_objects
.constEnd();
2356 for (; oi
!= oiEnd
; ++oi
)
2357 if ( !(*oi
)->m_bCompleted
)
2360 // Are we still parsing - or have we done the completed stuff already ?
2361 if ( d
->m_bComplete
|| (d
->m_doc
&& d
->m_doc
->parsing()) )
2364 // Still waiting for images/scripts from the loader ?
2366 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
2367 requests
= khtml::Cache::loader()->numRequests( d
->m_doc
->docLoader() );
2371 //kDebug(6050) << "still waiting for images/scripts from the loader - requests:" << requests;
2376 // Now do what should be done when we are really completed.
2377 d
->m_bComplete
= true;
2378 d
->m_cachePolicy
= KProtocolManager::cacheControl(); // reset cache policy
2379 d
->m_totalObjectCount
= 0;
2380 d
->m_loadedObjects
= 0;
2382 KHTMLPart
* p
= this;
2385 p
= p
->parentPart();
2386 if ( !p
&& !op
->d
->m_progressUpdateTimer
.isActive()) {
2387 op
->d
->m_progressUpdateTimer
.setSingleShot( true );
2388 op
->d
->m_progressUpdateTimer
.start( 0 );
2392 checkEmitLoadEvent(); // if we didn't do it before
2394 bool pendingAction
= false;
2396 if ( !d
->m_redirectURL
.isEmpty() )
2398 // DA: Do not start redirection for frames here! That action is
2399 // deferred until the parent emits a completed signal.
2400 if ( parentPart() == 0 ) {
2401 //kDebug(6050) << this << " starting redirection timer";
2402 d
->m_redirectionTimer
.setSingleShot( true );
2403 d
->m_redirectionTimer
.start( qMax(0, 1000 * d
->m_delayRedirect
) );
2405 //kDebug(6050) << this << " not toplevel -> not starting redirection timer. Waiting for slotParentCompleted.";
2408 pendingAction
= true;
2410 else if ( bPendingChildRedirection
)
2412 pendingAction
= true;
2415 // the view will emit completed on our behalf,
2416 // either now or at next repaint if one is pending
2418 //kDebug(6050) << this << " asks the view to emit completed. pendingAction=" << pendingAction;
2419 d
->m_view
->complete( pendingAction
);
2421 // find the alternate stylesheets
2424 sheets
= d
->m_doc
->availableStyleSheets();
2425 sheets
.prepend( i18n( "Automatic Detection" ) );
2426 d
->m_paUseStylesheet
->setItems( sheets
);
2428 d
->m_paUseStylesheet
->setEnabled( sheets
.count() > 2);
2429 if (sheets
.count() > 2)
2431 d
->m_paUseStylesheet
->setCurrentItem(qMax(sheets
.indexOf(d
->m_sheetUsed
), 0));
2432 slotUseStylesheet();
2435 setJSDefaultStatusBarText(QString());
2438 kDebug(6050) << "DONE: " <<d
->m_parsetime
.elapsed();
2442 void KHTMLPart::checkEmitLoadEvent()
2444 if ( d
->m_bLoadEventEmitted
|| !d
->m_doc
|| d
->m_doc
->parsing() ) return;
2446 ConstFrameIt it
= d
->m_frames
.constBegin();
2447 const ConstFrameIt end
= d
->m_frames
.constEnd();
2448 for (; it
!= end
; ++it
)
2449 if ( !(*it
)->m_bCompleted
) // still got a frame running -> too early
2452 ConstFrameIt oi
= d
->m_objects
.constBegin();
2453 const ConstFrameIt oiEnd
= d
->m_objects
.constEnd();
2455 for (; oi
!= oiEnd
; ++oi
)
2456 if ( !(*oi
)->m_bCompleted
) // still got a object running -> too early
2459 // Still waiting for images/scripts from the loader ?
2460 // (onload must happen afterwards, #45607)
2461 // ## This makes this method very similar to checkCompleted. A brave soul should try merging them.
2463 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
2464 requests
= khtml::Cache::loader()->numRequests( d
->m_doc
->docLoader() );
2469 d
->m_bLoadEventEmitted
= true;
2474 const KHTMLSettings
*KHTMLPart::settings() const
2476 return d
->m_settings
;
2479 #ifndef KDE_NO_COMPAT
2480 KUrl
KHTMLPart::baseURL() const
2482 if ( !d
->m_doc
) return KUrl();
2484 return d
->m_doc
->baseURL();
2488 KUrl
KHTMLPart::completeURL( const QString
&url
)
2490 if ( !d
->m_doc
) return KUrl( url
);
2494 return KUrl(d
->m_doc
->completeURL(url
), d
->m_decoder
->codec()->mibEnum());
2497 return KUrl( d
->m_doc
->completeURL( url
) );
2500 QString
KHTMLPartPrivate::codeForJavaScriptURL(const QString
&u
)
2502 return KUrl::fromPercentEncoding( u
.right( u
.length() - 11 ).toUtf8() );
2505 void KHTMLPartPrivate::executeJavascriptURL(const QString
&u
)
2507 QString script
= codeForJavaScriptURL(u
);
2508 kDebug( 6050 ) << "script=" << script
;
2509 QVariant res
= q
->executeScript( DOM::Node(), script
);
2510 if ( res
.type() == QVariant::String
) {
2511 q
->begin( q
->url() );
2512 q
->write( res
.toString() );
2515 emit q
->completed();
2518 bool KHTMLPartPrivate::isJavaScriptURL(const QString
& url
)
2520 return url
.indexOf( QLatin1String( "javascript:" ), 0, Qt::CaseInsensitive
) == 0;
2523 // Called by ecma/kjs_window in case of redirections from Javascript,
2524 // and by xml/dom_docimpl.cpp in case of http-equiv meta refresh.
2525 void KHTMLPart::scheduleRedirection( int delay
, const QString
&url
, bool doLockHistory
)
2527 kDebug(6050) << "delay=" << delay
<< " url=" << url
;
2528 kDebug(6050) << "current redirectURL=" << d
->m_redirectURL
<< " with delay " << d
->m_delayRedirect
;
2530 // In case of JS redirections, some, such as jump to anchors, and javascript:
2531 // evaluation should actually be handled immediately, and not waiting until
2532 // the end of the script. (Besides, we don't want to abort the tokenizer for those)
2533 if ( delay
== -1 && d
->isInPageURL(url
) ) {
2534 d
->executeInPageURL(url
, doLockHistory
);
2538 if( delay
< 24*60*60 &&
2539 ( d
->m_redirectURL
.isEmpty() || delay
<= d
->m_delayRedirect
) ) {
2540 d
->m_delayRedirect
= delay
;
2541 d
->m_redirectURL
= url
;
2542 d
->m_redirectLockHistory
= doLockHistory
;
2543 kDebug(6050) << " d->m_bComplete=" << d
->m_bComplete
;
2545 if ( d
->m_bComplete
) {
2546 d
->m_redirectionTimer
.stop();
2547 d
->m_redirectionTimer
.setSingleShot( true );
2548 d
->m_redirectionTimer
.start( qMax(0, 1000 * d
->m_delayRedirect
) );
2553 void KHTMLPartPrivate::clearRedirection()
2555 m_delayRedirect
= 0;
2556 m_redirectURL
.clear();
2557 m_redirectionTimer
.stop();
2560 void KHTMLPart::slotRedirect()
2562 kDebug(6050) << this;
2563 QString u
= d
->m_redirectURL
;
2565 d
->clearRedirection();
2567 if ( d
->isInPageURL(u
) )
2569 d
->executeInPageURL(u
, d
->m_redirectLockHistory
);
2573 KParts::OpenUrlArguments args
;
2574 KUrl
cUrl( this->url() );
2576 // handle windows opened by JS
2577 if ( openedByJS() && d
->m_opener
)
2578 cUrl
= d
->m_opener
->url();
2580 if (!KAuthorized::authorizeUrlAction("redirect", cUrl
, url
))
2582 kWarning(6050) << "KHTMLPart::scheduleRedirection: Redirection from " << cUrl
<< " to " << url
<< " REJECTED!";
2587 if ( urlcmp( u
, this->url().url(), KUrl::CompareWithoutTrailingSlash
| KUrl::CompareWithoutFragment
) )
2589 args
.metaData().insert("referrer", d
->m_pageReferrer
);
2592 // For javascript and META-tag based redirections:
2593 // - We don't take cross-domain-ness in consideration if we are the
2594 // toplevel frame because the new URL may be in a different domain as the current URL
2596 // - If we are not the toplevel frame then we check against the toplevelURL()
2598 args
.metaData().insert("cross-domain", toplevelURL().url());
2600 KParts::BrowserArguments browserArgs
;
2601 browserArgs
.setLockHistory( d
->m_redirectLockHistory
);
2602 // _self: make sure we don't use any <base target=>'s
2604 if ( !urlSelected( u
, 0, 0, "_self", args
, browserArgs
) ) {
2605 // urlSelected didn't open a url, so emit completed ourselves
2610 void KHTMLPart::slotRedirection(KIO::Job
*, const KUrl
& url
)
2612 // the slave told us that we got redirected
2613 //kDebug( 6050 ) << "redirection by KIO to" << url;
2614 emit d
->m_extension
->setLocationBarUrl( url
.prettyUrl() );
2615 d
->m_workingURL
= url
;
2618 bool KHTMLPart::setEncoding( const QString
&name
, bool override
)
2620 d
->m_encoding
= name
;
2621 d
->m_haveEncoding
= override
;
2623 if( !url().isEmpty() ) {
2626 KUrl oldUrl
= url();
2628 d
->m_restored
= true;
2630 d
->m_restored
= false;
2636 QString
KHTMLPart::encoding() const
2638 if(d
->m_haveEncoding
&& !d
->m_encoding
.isEmpty())
2639 return d
->m_encoding
;
2641 if(d
->m_decoder
&& d
->m_decoder
->encoding())
2642 return QString(d
->m_decoder
->encoding());
2644 return defaultEncoding();
2647 QString
KHTMLPart::defaultEncoding() const
2649 QString encoding
= settings()->encoding();
2650 if ( !encoding
.isEmpty() )
2652 // HTTP requires the default encoding to be latin1, when neither
2653 // the user nor the page requested a particular encoding.
2654 if ( url().protocol().startsWith( "http" ) )
2655 return "iso-8859-1";
2657 return KGlobal::locale()->encoding();
2660 void KHTMLPart::setUserStyleSheet(const KUrl
&url
)
2662 if ( d
->m_doc
&& d
->m_doc
->docLoader() )
2663 (void) new khtml::PartStyleSheetLoader(this, url
.url(), d
->m_doc
->docLoader());
2666 void KHTMLPart::setUserStyleSheet(const QString
&styleSheet
)
2669 d
->m_doc
->setUserStyleSheet( styleSheet
);
2672 bool KHTMLPart::gotoAnchor( const QString
&name
)
2677 HTMLCollectionImpl
*anchors
=
2678 new HTMLCollectionImpl( d
->m_doc
, HTMLCollectionImpl::DOC_ANCHORS
);
2680 NodeImpl
*n
= anchors
->namedItem(name
);
2684 n
= d
->m_doc
->getElementById( name
);
2687 d
->m_doc
->setCSSTarget(n
); // Setting to null will clear the current target.
2689 // Implement the rule that "" and "top" both mean top of page as in other browsers.
2690 bool quirkyName
= !n
&& !d
->m_doc
->inStrictMode() && (name
.isEmpty() || name
.toLower() == "top");
2693 d
->m_view
->setContentsPos( d
->m_view
->contentsX(), 0);
2696 kDebug(6050) << name
<< "not found";
2702 HTMLElementImpl
*a
= static_cast<HTMLElementImpl
*>(n
);
2704 a
->getUpperLeftCorner(x
, y
);
2705 if (x
<= d
->m_view
->contentsX())
2708 gox
= d
->m_view
->contentsX();
2709 if ( x
+ 10 > d
->m_view
->contentsX()+d
->m_view
->visibleWidth()) {
2710 a
->getLowerRightCorner(x
, dummy
);
2711 gox
= x
- d
->m_view
->visibleWidth() + 10;
2715 d
->m_view
->setContentsPos(gox
, y
);
2720 bool KHTMLPart::nextAnchor()
2724 d
->m_view
->focusNextPrevNode ( true );
2729 bool KHTMLPart::prevAnchor()
2733 d
->m_view
->focusNextPrevNode ( false );
2738 void KHTMLPart::setStandardFont( const QString
&name
)
2740 d
->m_settings
->setStdFontName(name
);
2743 void KHTMLPart::setFixedFont( const QString
&name
)
2745 d
->m_settings
->setFixedFontName(name
);
2748 void KHTMLPart::setURLCursor( const QCursor
&c
)
2750 d
->m_linkCursor
= c
;
2753 QCursor
KHTMLPart::urlCursor() const
2755 return d
->m_linkCursor
;
2758 bool KHTMLPart::onlyLocalReferences() const
2760 return d
->m_onlyLocalReferences
;
2763 void KHTMLPart::setOnlyLocalReferences(bool enable
)
2765 d
->m_onlyLocalReferences
= enable
;
2768 void KHTMLPartPrivate::setFlagRecursively(
2769 bool KHTMLPartPrivate::*flag
, bool value
)
2771 // first set it on the current one
2772 this->*flag
= value
;
2774 // descend into child frames recursively
2776 QList
<khtml::ChildFrame
*>::Iterator it
= m_frames
.begin();
2777 const QList
<khtml::ChildFrame
*>::Iterator itEnd
= m_frames
.end();
2778 for (; it
!= itEnd
; ++it
) {
2779 KHTMLPart
* const part
= qobject_cast
<KHTMLPart
*>( (*it
)->m_part
);
2781 part
->d
->setFlagRecursively(flag
, value
);
2784 // do the same again for objects
2786 QList
<khtml::ChildFrame
*>::Iterator it
= m_objects
.begin();
2787 const QList
<khtml::ChildFrame
*>::Iterator itEnd
= m_objects
.end();
2788 for (; it
!= itEnd
; ++it
) {
2789 KHTMLPart
* const part
= qobject_cast
<KHTMLPart
*>( (*it
)->m_part
);
2791 part
->d
->setFlagRecursively(flag
, value
);
2796 void KHTMLPart::initCaret()
2798 // initialize caret if not used yet
2799 if (d
->editor_context
.m_selection
.state() == Selection::NONE
) {
2802 if (d
->m_doc
->isHTMLDocument()) {
2803 HTMLDocumentImpl
* htmlDoc
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
);
2804 node
= htmlDoc
->body();
2808 d
->editor_context
.m_selection
.moveTo(Position(node
, 0));
2809 d
->editor_context
.m_selection
.setNeedsLayout();
2810 d
->editor_context
.m_selection
.needsCaretRepaint();
2815 static void setCaretInvisibleIfNeeded(KHTMLPart
*part
)
2817 // On contenteditable nodes, don't hide the caret
2818 if (!khtml::KHTMLPartAccessor::caret(part
).caretPos().node()->isContentEditable())
2819 part
->setCaretVisible(false);
2822 void KHTMLPart::setCaretMode(bool enable
)
2824 kDebug(6200) << enable
;
2825 if (isCaretMode() == enable
) return;
2826 d
->setFlagRecursively(&KHTMLPartPrivate::m_caretMode
, enable
);
2827 // FIXME: this won't work on frames as expected
2828 if (!isEditable()) {
2831 setCaretVisible(true);
2832 // view()->ensureCaretVisible();
2834 setCaretInvisibleIfNeeded(this);
2839 bool KHTMLPart::isCaretMode() const
2841 return d
->m_caretMode
;
2844 void KHTMLPart::setEditable(bool enable
)
2846 if (isEditable() == enable
) return;
2847 d
->setFlagRecursively(&KHTMLPartPrivate::m_designMode
, enable
);
2848 // FIXME: this won't work on frames as expected
2849 if (!isCaretMode()) {
2852 setCaretVisible(true);
2853 // view()->ensureCaretVisible();
2855 setCaretInvisibleIfNeeded(this);
2859 bool KHTMLPart::isEditable() const
2861 return d
->m_designMode
;
2864 khtml::EditorContext
*KHTMLPart::editorContext() const {
2865 return &d
->editor_context
;
2868 void KHTMLPart::setCaretPosition(DOM::Node node
, long offset
, bool extendSelection
)
2870 #ifndef KHTML_NO_CARET
2872 kDebug(6200) << "node: " << node
.handle() << " nodeName: "
2873 << node
.nodeName().string() << " offset: " << offset
2874 << " extendSelection " << extendSelection
;
2875 if (view()->moveCaretTo(node
.handle(), offset
, !extendSelection
))
2876 emitSelectionChanged();
2877 view()->ensureCaretVisible();
2879 #endif // KHTML_NO_CARET
2882 KHTMLPart::CaretDisplayPolicy
KHTMLPart::caretDisplayPolicyNonFocused() const
2885 #ifndef KHTML_NO_CARET
2886 return (CaretDisplayPolicy
)view()->caretDisplayPolicyNonFocused();
2887 #else // KHTML_NO_CARET
2888 return CaretInvisible
;
2889 #endif // KHTML_NO_CARET
2891 return CaretInvisible
;
2894 void KHTMLPart::setCaretDisplayPolicyNonFocused(CaretDisplayPolicy policy
)
2897 #ifndef KHTML_NO_CARET
2898 view()->setCaretDisplayPolicyNonFocused(policy
);
2899 #endif // KHTML_NO_CARET
2903 void KHTMLPart::setCaretVisible(bool show
)
2906 NodeImpl
*caretNode
= d
->editor_context
.m_selection
.caretPos().node();
2907 if (isCaretMode() || (caretNode
&& caretNode
->isContentEditable())) {
2908 invalidateSelection();
2909 enableFindAheadActions(false);
2913 if (d
->editor_context
.m_caretBlinkTimer
>= 0)
2914 killTimer(d
->editor_context
.m_caretBlinkTimer
);
2915 clearCaretRectIfNeeded();
2920 void KHTMLPart::findTextBegin()
2922 d
->m_find
.findTextBegin();
2925 bool KHTMLPart::initFindNode( bool selection
, bool reverse
, bool fromCursor
)
2927 return d
->m_find
.initFindNode(selection
, reverse
, fromCursor
);
2930 void KHTMLPart::slotFind()
2932 KParts::ReadOnlyPart
*part
= currentFrame();
2935 if (!part
->inherits("KHTMLPart") )
2937 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2940 static_cast<KHTMLPart
*>( part
)->findText();
2943 void KHTMLPart::slotFindNext()
2945 KParts::ReadOnlyPart
*part
= currentFrame();
2948 if (!part
->inherits("KHTMLPart") )
2950 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2953 static_cast<KHTMLPart
*>( part
)->findTextNext();
2956 void KHTMLPart::slotFindPrev()
2958 KParts::ReadOnlyPart
*part
= currentFrame();
2961 if (!part
->inherits("KHTMLPart") )
2963 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2966 static_cast<KHTMLPart
*>( part
)->findTextNext( true ); // reverse
2969 void KHTMLPart::slotFindDone()
2974 void KHTMLPart::slotFindAheadText()
2976 #ifndef KHTML_NO_TYPE_AHEAD_FIND
2977 KParts::ReadOnlyPart
*part
= currentFrame();
2980 if (!part
->inherits("KHTMLPart") )
2982 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
2985 static_cast<KHTMLPart
*>( part
)->view()->startFindAhead( false );
2986 #endif // KHTML_NO_TYPE_AHEAD_FIND
2989 void KHTMLPart::slotFindAheadLink()
2991 #ifndef KHTML_NO_TYPE_AHEAD_FIND
2992 KParts::ReadOnlyPart
*part
= currentFrame();
2995 if (!part
->inherits("KHTMLPart") )
2997 kError(6000) << "part is a" << part
->metaObject()->className() << ", can't do a search into it";
3000 static_cast<KHTMLPart
*>( part
)->view()->startFindAhead( true );
3001 #endif // KHTML_NO_TYPE_AHEAD_FIND
3004 void KHTMLPart::enableFindAheadActions( bool enable
)
3006 // only the topmost one has shortcuts
3007 KHTMLPart
* p
= this;
3008 while( p
->parentPart())
3009 p
= p
->parentPart();
3010 p
->d
->m_paFindAheadText
->setEnabled( enable
);
3011 p
->d
->m_paFindAheadLinks
->setEnabled( enable
);
3014 void KHTMLPart::slotFindDialogDestroyed()
3019 void KHTMLPart::findText()
3022 return parentPart()->findText();
3023 d
->m_find
.activate();
3026 void KHTMLPart::findText( const QString
&str
, long options
, QWidget
*parent
, KFindDialog
*findDialog
)
3029 return parentPart()->findText(str
, options
, parent
, findDialog
);
3030 d
->m_find
.createNewKFind(str
, options
, parent
, findDialog
);
3034 bool KHTMLPart::findTextNext( bool reverse
)
3037 return parentPart()->findTextNext( reverse
);
3038 return d
->m_find
.findTextNext( reverse
);
3041 QString
KHTMLPart::selectedTextAsHTML() const
3043 const Selection
&sel
= d
->editor_context
.m_selection
;
3044 if(!hasSelection()) {
3045 kDebug() << "Selection is not valid. Returning empty selection";
3048 if(sel
.start().offset() < 0 || sel
.end().offset() < 0) {
3049 kDebug() << "invalid values for end/startOffset " << sel
.start().offset() << " " << sel
.end().offset();
3052 DOM::Range r
= selection();
3053 if(r
.isNull() || r
.isDetached())
3055 int exceptioncode
= 0; //ignore the result
3056 return r
.handle()->toHTML(exceptioncode
).string();
3059 QString
KHTMLPart::selectedText() const
3061 bool hasNewLine
= true;
3062 bool seenTDTag
= false;
3064 const Selection
&sel
= d
->editor_context
.m_selection
;
3065 DOM::Node n
= sel
.start().node();
3066 while(!n
.isNull()) {
3067 if(n
.nodeType() == DOM::Node::TEXT_NODE
&& n
.handle()->renderer()) {
3068 DOM::DOMStringImpl
*dstr
= static_cast<DOM::TextImpl
*>(n
.handle())->renderString();
3069 QString
str(dstr
->s
, dstr
->l
);
3070 if(!str
.isEmpty()) {
3076 if(n
== sel
.start().node() && n
== sel
.end().node())
3077 text
= str
.mid(sel
.start().offset(), sel
.end().offset() - sel
.start().offset());
3078 else if(n
== sel
.start().node())
3079 text
= str
.mid(sel
.start().offset());
3080 else if(n
== sel
.end().node())
3081 text
+= str
.left(sel
.end().offset());
3087 // This is our simple HTML -> ASCII transformation:
3088 unsigned short id
= n
.elementId();
3091 text
+= static_cast<HTMLTextAreaElementImpl
*>(n
.handle())->value().string();
3094 if (static_cast<HTMLInputElementImpl
*>(n
.handle())->inputType() != HTMLInputElementImpl::PASSWORD
)
3095 text
+= static_cast<HTMLInputElementImpl
*>(n
.handle())->value().string();
3098 text
+= static_cast<HTMLSelectElementImpl
*>(n
.handle())->value().string();
3105 text
+= static_cast<HTMLImageElementImpl
*>(n
.handle())->altText().string();
3139 if(n
== sel
.end().node()) break;
3140 DOM::Node next
= n
.firstChild();
3141 if(next
.isNull()) next
= n
.nextSibling();
3142 while( next
.isNull() && !n
.parentNode().isNull() ) {
3144 next
= n
.nextSibling();
3145 unsigned short id
= n
.elementId();
3148 seenTDTag
= true; //Add two spaces after a td if then followed by text.
3190 int end
= text
.length();
3192 // Strip leading LFs
3193 while ((start
< end
) && (text
[start
] == '\n'))
3196 // Strip excessive trailing LFs
3197 while ((start
< (end
-1)) && (text
[end
-1] == '\n') && (text
[end
-2] == '\n'))
3200 return text
.mid(start
, end
-start
);
3203 QString
KHTMLPart::simplifiedSelectedText() const
3205 QString text
= selectedText();
3206 text
.replace(QChar(0xa0), ' ');
3207 // remove leading and trailing whitespace
3208 while (!text
.isEmpty() && text
[0].isSpace())
3210 while (!text
.isEmpty() && text
[text
.length()-1].isSpace())
3211 text
.truncate(text
.length()-1);
3215 bool KHTMLPart::hasSelection() const
3217 return !d
->editor_context
.m_selection
.isEmpty() && !d
->editor_context
.m_selection
.isCollapsed();
3220 DOM::Range
KHTMLPart::selection() const
3222 return d
->editor_context
.m_selection
.toRange();
3225 void KHTMLPart::selection(DOM::Node
&s
, long &so
, DOM::Node
&e
, long &eo
) const
3227 DOM::Range r
= d
->editor_context
.m_selection
.toRange();
3228 s
= r
.startContainer();
3229 so
= r
.startOffset();
3230 e
= r
.endContainer();
3234 void KHTMLPart::setSelection( const DOM::Range
&r
)
3239 const Selection
&KHTMLPart::caret() const
3241 return d
->editor_context
.m_selection
;
3244 const Selection
&KHTMLPart::dragCaret() const
3246 return d
->editor_context
.m_dragCaret
;
3249 void KHTMLPart::setCaret(const Selection
&s
, bool closeTyping
)
3251 if (d
->editor_context
.m_selection
!= s
) {
3252 clearCaretRectIfNeeded();
3253 setFocusNodeIfNeeded(s
);
3254 d
->editor_context
.m_selection
= s
;
3255 notifySelectionChanged(closeTyping
);
3259 void KHTMLPart::setDragCaret(const DOM::Selection
&dragCaret
)
3261 if (d
->editor_context
.m_dragCaret
!= dragCaret
) {
3262 d
->editor_context
.m_dragCaret
.needsCaretRepaint();
3263 d
->editor_context
.m_dragCaret
= dragCaret
;
3264 d
->editor_context
.m_dragCaret
.needsCaretRepaint();
3268 void KHTMLPart::clearSelection()
3270 clearCaretRectIfNeeded();
3271 setFocusNodeIfNeeded(d
->editor_context
.m_selection
);
3272 #ifdef APPLE_CHANGES
3273 d
->editor_context
.m_selection
.clear();
3275 d
->editor_context
.m_selection
.collapse();
3277 notifySelectionChanged();
3280 void KHTMLPart::invalidateSelection()
3282 clearCaretRectIfNeeded();
3283 d
->editor_context
.m_selection
.setNeedsLayout();
3284 selectionLayoutChanged();
3287 void KHTMLPart::setSelectionVisible(bool flag
)
3289 if (d
->editor_context
.m_caretVisible
== flag
)
3292 clearCaretRectIfNeeded();
3293 setFocusNodeIfNeeded(d
->editor_context
.m_selection
);
3294 d
->editor_context
.m_caretVisible
= flag
;
3295 // notifySelectionChanged();
3299 void KHTMLPart::slotClearSelection()
3302 && d
->editor_context
.m_selection
.state() != Selection::NONE
3303 && !d
->editor_context
.m_selection
.caretPos().node()->isContentEditable())
3304 clearCaretRectIfNeeded();
3305 bool hadSelection
= hasSelection();
3306 #ifdef APPLE_CHANGES
3307 d
->editor_context
.m_selection
.clear();
3309 d
->editor_context
.m_selection
.collapse();
3312 notifySelectionChanged();
3316 void KHTMLPart::clearCaretRectIfNeeded()
3318 if (d
->editor_context
.m_caretPaint
) {
3319 d
->editor_context
.m_caretPaint
= false;
3320 d
->editor_context
.m_selection
.needsCaretRepaint();
3324 void KHTMLPart::setFocusNodeIfNeeded(const Selection
&s
)
3326 if (!xmlDocImpl() || s
.state() == Selection::NONE
)
3329 NodeImpl
*n
= s
.start().node();
3330 NodeImpl
*target
= (n
&& n
->isContentEditable()) ? n
: 0;
3332 while (n
&& n
!= s
.end().node()) {
3333 if (n
->isContentEditable()) {
3337 n
= n
->traverseNextNode();
3340 assert(target
== 0 || target
->isContentEditable());
3343 for ( ; target
&& !target
->isFocusable(); target
= target
->parentNode())
3345 if (target
&& target
->isMouseFocusable())
3346 xmlDocImpl()->setFocusNode(target
);
3347 else if (!target
|| !target
->focused())
3348 xmlDocImpl()->setFocusNode(0);
3352 void KHTMLPart::selectionLayoutChanged()
3354 // kill any caret blink timer now running
3355 if (d
->editor_context
.m_caretBlinkTimer
>= 0) {
3356 killTimer(d
->editor_context
.m_caretBlinkTimer
);
3357 d
->editor_context
.m_caretBlinkTimer
= -1;
3360 // see if a new caret blink timer needs to be started
3361 if (d
->editor_context
.m_caretVisible
3362 && d
->editor_context
.m_selection
.state() != Selection::NONE
) {
3363 d
->editor_context
.m_caretPaint
= isCaretMode()
3364 || d
->editor_context
.m_selection
.caretPos().node()->isContentEditable();
3365 if (d
->editor_context
.m_caretBlinks
&& d
->editor_context
.m_caretPaint
)
3366 d
->editor_context
.m_caretBlinkTimer
= startTimer(qApp
->cursorFlashTime() / 2);
3367 d
->editor_context
.m_selection
.needsCaretRepaint();
3371 d
->m_doc
->updateSelection();
3373 // Always clear the x position used for vertical arrow navigation.
3374 // It will be restored by the vertical arrow navigation code if necessary.
3375 d
->editor_context
.m_xPosForVerticalArrowNavigation
= d
->editor_context
.NoXPosForVerticalArrowNavigation
;
3378 void KHTMLPart::notifySelectionChanged(bool closeTyping
)
3380 Editor
*ed
= d
->editor_context
.m_editor
;
3381 selectionLayoutChanged();
3383 ed
->clearTypingStyle();
3386 khtml::TypingCommand::closeTyping(ed
->lastEditCommand());
3389 emitSelectionChanged();
3393 void KHTMLPart::timerEvent(QTimerEvent
*e
)
3395 if (e
->timerId() == d
->editor_context
.m_caretBlinkTimer
) {
3396 if (d
->editor_context
.m_caretBlinks
&&
3397 d
->editor_context
.m_selection
.state() != Selection::NONE
) {
3398 d
->editor_context
.m_caretPaint
= !d
->editor_context
.m_caretPaint
;
3399 d
->editor_context
.m_selection
.needsCaretRepaint();
3401 } else if (e
->timerId() == d
->m_DNSPrefetchTimer
) {
3402 // kDebug( 6050 ) << "will lookup " << d->m_DNSPrefetchQueue.head() << d->m_numDNSPrefetchedNames;
3403 KIO::HostInfo::prefetchHost( d
->m_DNSPrefetchQueue
.dequeue() );
3404 if (d
->m_DNSPrefetchQueue
.isEmpty()) {
3405 killTimer( d
->m_DNSPrefetchTimer
);
3406 d
->m_DNSPrefetchTimer
= -1;
3408 } else if (e
->timerId() == d
->m_DNSTTLTimer
) {
3409 foreach (QString name
, d
->m_lookedupHosts
)
3410 d
->m_DNSPrefetchQueue
.enqueue(name
);
3411 if (d
->m_DNSPrefetchTimer
<= 0)
3412 d
->m_DNSPrefetchTimer
= startTimer( sDNSPrefetchTimerDelay
);
3416 bool KHTMLPart::mayPrefetchHostname( const QString
& name
)
3418 if (d
->m_bDNSPrefetch
== DNSPrefetchDisabled
)
3421 if (d
->m_numDNSPrefetchedNames
>= sMaxDNSPrefetchPerPage
)
3424 if (d
->m_bDNSPrefetch
== DNSPrefetchOnlyWWWAndSLD
) {
3425 int dots
= name
.count('.');
3426 if (dots
> 2 || (dots
== 2 && !name
.startsWith("www.")))
3430 if ( d
->m_lookedupHosts
.contains( name
) )
3433 d
->m_DNSPrefetchQueue
.enqueue( name
);
3434 d
->m_lookedupHosts
.insert( name
);
3435 d
->m_numDNSPrefetchedNames
++;
3437 if (d
->m_DNSPrefetchTimer
< 1)
3438 d
->m_DNSPrefetchTimer
= startTimer( sDNSPrefetchTimerDelay
);
3439 if (d
->m_DNSTTLTimer
< 1)
3440 d
->m_DNSTTLTimer
= startTimer( sDNSTTLSeconds
*1000 + 1 );
3445 void KHTMLPart::paintCaret(QPainter
*p
, const QRect
&rect
) const
3447 if (d
->editor_context
.m_caretPaint
)
3448 d
->editor_context
.m_selection
.paintCaret(p
, rect
);
3451 void KHTMLPart::paintDragCaret(QPainter
*p
, const QRect
&rect
) const
3453 d
->editor_context
.m_dragCaret
.paintCaret(p
, rect
);
3456 DOM::Editor
*KHTMLPart::editor() const {
3457 if (!d
->editor_context
.m_editor
)
3458 const_cast<KHTMLPart
*>(this)->d
->editor_context
.m_editor
= new DOM::Editor(const_cast<KHTMLPart
*>(this));
3459 return d
->editor_context
.m_editor
;
3462 void KHTMLPart::resetHoverText()
3464 if( !d
->m_overURL
.isEmpty() ) // Only if we were showing a link
3466 d
->m_overURL
.clear();
3467 d
->m_overURLTarget
.clear();
3468 emit
onURL( QString() );
3469 // revert to default statusbar text
3470 setStatusBarText(QString(), BarHoverText
);
3471 emit d
->m_extension
->mouseOverInfo(KFileItem());
3475 void KHTMLPart::overURL( const QString
&url
, const QString
&target
, bool /*shiftPressed*/ )
3477 KUrl u
= completeURL(url
);
3479 // special case for <a href="">
3480 if ( url
.isEmpty() )
3481 u
.setFileName( url
);
3485 if ( url
.isEmpty() ) {
3486 setStatusBarText(Qt::escape(u
.prettyUrl()), BarHoverText
);
3490 if ( d
->isJavaScriptURL(url
) ) {
3491 QString jscode
= d
->codeForJavaScriptURL( url
);
3492 jscode
= KStringHandler::rsqueeze( jscode
, 80 ); // truncate if too long
3493 if (url
.startsWith("javascript:window.open"))
3494 jscode
+= i18n(" (In new window)");
3495 setStatusBarText( Qt::escape( jscode
), BarHoverText
);
3499 KFileItem
item(u
, QString(), KFileItem::Unknown
);
3500 emit d
->m_extension
->mouseOverInfo(item
);
3504 KMimeType::Ptr typ
= KMimeType::findByUrl( u
);
3507 com
= typ
->comment( u
);
3509 if ( !u
.isValid() ) {
3510 setStatusBarText(Qt::escape(u
.prettyUrl()), BarHoverText
);
3514 if ( u
.isLocalFile() )
3516 // TODO : use KIO::stat() and create a KFileItem out of its result,
3517 // to use KFileItem::statusBarText()
3518 const QString path
= QFile::encodeName( u
.toLocalFile() );
3520 KDE_struct_stat buff
;
3521 bool ok
= !KDE::stat( path
, &buff
);
3523 KDE_struct_stat lbuff
;
3524 if (ok
) ok
= !KDE::lstat( path
, &lbuff
);
3526 QString text
= Qt::escape(u
.prettyUrl());
3527 QString text2
= text
;
3529 if (ok
&& S_ISLNK( lbuff
.st_mode
) )
3533 tmp
= i18n( "Symbolic Link");
3535 tmp
= i18n("%1 (Link)", com
);
3536 char buff_two
[1024];
3538 int n
= readlink ( path
.toLocal8Bit().data(), buff_two
, 1022);
3543 setStatusBarText(text2
, BarHoverText
);
3552 else if ( ok
&& S_ISREG( buff
.st_mode
) )
3554 if (buff
.st_size
< 1024)
3555 text
= i18n("%2 (%1 bytes)", (long) buff
.st_size
, text2
); // always put the URL last, in case it contains '%'
3558 float d
= (float) buff
.st_size
/1024.0;
3559 text
= i18n("%2 (%1 K)", KGlobal::locale()->formatNumber(d
, 2), text2
); // was %.2f
3564 else if ( ok
&& S_ISDIR( buff
.st_mode
) )
3574 setStatusBarText(text
, BarHoverText
);
3579 if (target
.toLower() == "_blank")
3581 extra
= i18n(" (In new window)");
3583 else if (!target
.isEmpty() &&
3584 (target
.toLower() != "_top") &&
3585 (target
.toLower() != "_self") &&
3586 (target
.toLower() != "_parent"))
3588 KHTMLPart
*p
= this;
3589 while (p
->parentPart())
3590 p
= p
->parentPart();
3591 if (!p
->frameExists(target
))
3592 extra
= i18n(" (In new window)");
3594 extra
= i18n(" (In other frame)");
3597 if (u
.protocol() == QLatin1String("mailto")) {
3598 QString mailtoMsg
/* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
3599 mailtoMsg
+= i18n("Email to: ") + KUrl::fromPercentEncoding(u
.path().toLatin1());
3600 const QStringList queries
= u
.query().mid(1).split('&');
3601 QStringList::ConstIterator it
= queries
.begin();
3602 const QStringList::ConstIterator itEnd
= queries
.end();
3603 for (; it
!= itEnd
; ++it
)
3604 if ((*it
).startsWith(QLatin1String("subject=")))
3605 mailtoMsg
+= i18n(" - Subject: ") + KUrl::fromPercentEncoding((*it
).mid(8).toLatin1());
3606 else if ((*it
).startsWith(QLatin1String("cc=")))
3607 mailtoMsg
+= i18n(" - CC: ") + KUrl::fromPercentEncoding((*it
).mid(3).toLatin1());
3608 else if ((*it
).startsWith(QLatin1String("bcc=")))
3609 mailtoMsg
+= i18n(" - BCC: ") + KUrl::fromPercentEncoding((*it
).mid(4).toLatin1());
3610 mailtoMsg
= Qt::escape(mailtoMsg
);
3611 mailtoMsg
.replace(QRegExp("([\n\r\t]|[ ]{10})"), QString());
3612 setStatusBarText("<qt>"+mailtoMsg
, BarHoverText
);
3615 // Is this check necessary at all? (Frerich)
3617 else if (u
.protocol() == QLatin1String("http")) {
3618 DOM::Node hrefNode
= nodeUnderMouse().parentNode();
3619 while (hrefNode
.nodeName().string() != QLatin1String("A") && !hrefNode
.isNull())
3620 hrefNode
= hrefNode
.parentNode();
3622 if (!hrefNode
.isNull()) {
3623 DOM::Node hreflangNode
= hrefNode
.attributes().getNamedItem("HREFLANG");
3624 if (!hreflangNode
.isNull()) {
3625 QString countryCode
= hreflangNode
.nodeValue().string().toLower();
3626 // Map the language code to an appropriate country code.
3627 if (countryCode
== QLatin1String("en"))
3628 countryCode
= QLatin1String("gb");
3629 QString flagImg
= QLatin1String("<img src=%1>").arg(
3630 locate("locale", QLatin1String("l10n/")
3632 + QLatin1String("/flag.png")));
3633 emit
setStatusBarText(flagImg
+ u
.prettyUrl() + extra
);
3638 setStatusBarText(Qt::escape(u
.prettyUrl()) + extra
, BarHoverText
);
3643 // This executes in the active part on a click or other url selection action in
3644 // that active part.
3646 bool KHTMLPart::urlSelected( const QString
&url
, int button
, int state
, const QString
&_target
, const KParts::OpenUrlArguments
& _args
, const KParts::BrowserArguments
& _browserArgs
)
3648 KParts::OpenUrlArguments args
= _args
;
3649 KParts::BrowserArguments browserArgs
= _browserArgs
;
3650 bool hasTarget
= false;
3652 QString target
= _target
;
3653 if ( target
.isEmpty() && d
->m_doc
)
3654 target
= d
->m_doc
->baseTarget();
3655 if ( !target
.isEmpty() )
3658 if ( d
->isJavaScriptURL(url
) )
3660 crossFrameExecuteScript( target
, d
->codeForJavaScriptURL(url
) );
3664 KUrl cURL
= completeURL(url
);
3665 // special case for <a href=""> (IE removes filename, mozilla doesn't)
3666 if ( url
.isEmpty() )
3667 cURL
.setFileName( url
); // removes filename
3669 if ( !cURL
.isValid() )
3670 // ### ERROR HANDLING
3673 kDebug(6050) << this << "complete URL:" << cURL
.url() << "target=" << target
;
3675 if ( state
& Qt::ControlModifier
)
3677 browserArgs
.setNewTab(true);
3678 emit d
->m_extension
->createNewWindow( cURL
, args
, browserArgs
);
3682 if ( button
== Qt::LeftButton
&& ( state
& Qt::ShiftModifier
) )
3684 KIO::MetaData metaData
;
3685 metaData
.insert( "referrer", d
->m_referrer
);
3686 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n( "Save As" ), cURL
, metaData
);
3690 if (!checkLinkSecurity(cURL
,
3691 ki18n( "<qt>This untrusted page links to<br /><b>%1</b>.<br />Do you want to follow the link?</qt>" ),
3695 browserArgs
.frameName
= target
;
3697 args
.metaData().insert("main_frame_request",
3698 parentPart() == 0 ? "TRUE":"FALSE");
3699 args
.metaData().insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
3700 args
.metaData().insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
3701 args
.metaData().insert("PropagateHttpHeader", "true");
3702 args
.metaData().insert("ssl_was_in_use", d
->m_ssl_in_use
? "TRUE":"FALSE");
3703 args
.metaData().insert("ssl_activate_warnings", "TRUE");
3705 if ( hasTarget
&& target
!= "_self" && target
!= "_top" && target
!= "_blank" && target
!= "_parent" )
3707 // unknown frame names should open in a new window.
3708 khtml::ChildFrame
*frame
= recursiveFrameRequest( this, cURL
, args
, browserArgs
, false );
3711 args
.metaData()["referrer"] = d
->m_referrer
;
3712 requestObject( frame
, cURL
, args
, browserArgs
);
3717 if (!d
->m_referrer
.isEmpty() && !args
.metaData().contains("referrer"))
3718 args
.metaData()["referrer"] = d
->m_referrer
;
3720 if ( button
== Qt::NoButton
&& (state
& Qt::ShiftModifier
) && (state
& Qt::ControlModifier
) )
3722 emit d
->m_extension
->createNewWindow( cURL
, args
, browserArgs
);
3726 if ( state
& Qt::ShiftModifier
)
3728 KParts::WindowArgs winArgs
;
3729 winArgs
.setLowerWindow(true);
3730 emit d
->m_extension
->createNewWindow( cURL
, args
, browserArgs
, winArgs
);
3734 //If we're asked to open up an anchor in the current URL, in current window,
3735 //merely gotoanchor, and do not reload the new page. Note that this does
3736 //not apply if the URL is the same page, but without a ref
3737 if (cURL
.hasRef() && (!hasTarget
|| target
== "_self"))
3739 if (d
->isLocalAnchorJump(cURL
))
3741 d
->executeAnchorJump(cURL
, browserArgs
.lockHistory() );
3742 return false; // we jumped, but we didn't open a URL
3746 if ( !d
->m_bComplete
&& !hasTarget
)
3749 view()->viewport()->unsetCursor();
3750 emit d
->m_extension
->openUrlRequest( cURL
, args
, browserArgs
);
3754 void KHTMLPart::slotViewDocumentSource()
3756 KUrl
currentUrl(this->url());
3757 bool isTempFile
= false;
3758 if (!(currentUrl
.isLocalFile()) && KHTMLPageCache::self()->isComplete(d
->m_cacheId
))
3760 KTemporaryFile sourceFile
;
3761 sourceFile
.setSuffix(defaultExtension());
3762 sourceFile
.setAutoRemove(false);
3763 if (sourceFile
.open())
3765 QDataStream
stream ( &sourceFile
);
3766 KHTMLPageCache::self()->saveData(d
->m_cacheId
, &stream
);
3767 currentUrl
= KUrl();
3768 currentUrl
.setPath(sourceFile
.fileName());
3773 (void) KRun::runUrl( currentUrl
, QLatin1String("text/plain"), view(), isTempFile
);
3776 void KHTMLPart::slotViewPageInfo()
3780 QDialog
*dlg
= new QDialog(0);
3781 dlg
->setAttribute(Qt::WA_DeleteOnClose
);
3782 dlg
->setObjectName("KHTML Page Info Dialog");
3785 ui
._close
->setGuiItem(KStandardGuiItem::close());
3787 connect(ui
._close
, SIGNAL(clicked()), dlg
, SLOT(accept()));
3789 ui
._title
->setText(d
->m_doc
->title().string());
3791 // If it's a frame, set the caption to "Frame Information"
3792 if ( parentPart() && d
->m_doc
&& d
->m_doc
->isHTMLDocument() ) {
3793 dlg
->setWindowTitle(i18n("Frame Information"));
3798 if (!d
->m_pageServices
.isEmpty())
3799 editStr
= i18n(" <a href=\"%1\">[Properties]</a>", d
->m_pageServices
);
3801 QString squeezedURL
= KStringHandler::csqueeze( url().prettyUrl(), 80 );
3802 ui
._url
->setText("<a href=\"" + url().url() + "\">" + squeezedURL
+ "</a>" + editStr
);
3803 if (lastModified().isEmpty())
3805 ui
._lastModified
->hide();
3806 ui
._lmLabel
->hide();
3809 ui
._lastModified
->setText(lastModified());
3811 const QString
& enc
= encoding();
3812 if (enc
.isEmpty()) {
3814 ui
._encoding
->hide();
3816 ui
._encoding
->setText(enc
);
3818 /* populate the list view now */
3819 const QStringList headers
= d
->m_httpHeaders
.split("\n");
3821 QStringList::ConstIterator it
= headers
.begin();
3822 const QStringList::ConstIterator itEnd
= headers
.end();
3824 for (; it
!= itEnd
; ++it
) {
3825 const QStringList header
= (*it
).split(QRegExp(":[ ]+"));
3826 if (header
.count() != 2)
3828 QTreeWidgetItem
*item
= new QTreeWidgetItem(ui
._headers
);
3829 item
->setText(0, header
[0]);
3830 item
->setText(1, header
[1]);
3834 /* put no code here */
3838 void KHTMLPart::slotViewFrameSource()
3840 KParts::ReadOnlyPart
*frame
= currentFrame();
3844 KUrl url
= frame
->url();
3845 bool isTempFile
= false;
3846 if (!(url
.isLocalFile()) && frame
->inherits("KHTMLPart"))
3848 long cacheId
= static_cast<KHTMLPart
*>(frame
)->d
->m_cacheId
;
3850 if (KHTMLPageCache::self()->isComplete(cacheId
))
3852 KTemporaryFile sourceFile
;
3853 sourceFile
.setSuffix(defaultExtension());
3854 sourceFile
.setAutoRemove(false);
3855 if (sourceFile
.open())
3857 QDataStream
stream ( &sourceFile
);
3858 KHTMLPageCache::self()->saveData(cacheId
, &stream
);
3860 url
.setPath(sourceFile
.fileName());
3866 (void) KRun::runUrl( url
, QLatin1String("text/plain"), view(), isTempFile
);
3869 KUrl
KHTMLPart::backgroundURL() const
3871 // ### what about XML documents? get from CSS?
3872 if (!d
->m_doc
|| !d
->m_doc
->isHTMLDocument())
3875 QString relURL
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body()->getAttribute( ATTR_BACKGROUND
).string();
3877 return KUrl( url(), relURL
);
3880 void KHTMLPart::slotSaveBackground()
3882 KIO::MetaData metaData
;
3883 metaData
["referrer"] = d
->m_referrer
;
3884 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n("Save Background Image As"), backgroundURL(), metaData
);
3887 void KHTMLPart::slotSaveDocument()
3889 KUrl
srcURL( url() );
3891 if ( srcURL
.fileName(KUrl::ObeyTrailingSlash
).isEmpty() )
3892 srcURL
.setFileName( "index" + defaultExtension() );
3894 KIO::MetaData metaData
;
3896 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n( "Save As" ), srcURL
, metaData
, "text/html", d
->m_cacheId
);
3899 void KHTMLPart::slotSecurity()
3901 // kDebug( 6050 ) << "Meta Data:" << endl
3902 // << d->m_ssl_peer_cert_subject
3904 // << d->m_ssl_peer_cert_issuer
3906 // << d->m_ssl_cipher
3908 // << d->m_ssl_cipher_desc
3910 // << d->m_ssl_cipher_version
3912 // << d->m_ssl_good_from
3914 // << d->m_ssl_good_until
3916 // << d->m_ssl_cert_state
3919 //### reenable with new signature
3921 KSSLInfoDialog
*kid
= new KSSLInfoDialog(d
->m_ssl_in_use
, widget(), "kssl_info_dlg", true );
3923 const QStringList sl
= d
->m_ssl_peer_chain
.split('\n', QString::SkipEmptyParts
);
3924 QList
<QSslCertificate
> certChain
;
3925 bool certChainOk
= d
->m_ssl_in_use
;
3927 foreach (const QString
&s
, sl
) {
3928 certChain
.append(QSslCertificate(s
.toAscii())); //or is it toLocal8Bit or whatever?
3929 if (certChain
.last().isNull()) {
3930 certChainOk
= false;
3936 kid
->setup(certChain
,
3940 d
->m_ssl_cipher_desc
,
3941 d
->m_ssl_cipher_version
,
3942 d
->m_ssl_cipher_used_bits
.toInt(),
3943 d
->m_ssl_cipher_bits
.toInt(),
3944 (KSSLCertificate::KSSLValidation
) d
->m_ssl_cert_state
.toInt());
3947 //the dialog deletes itself on close
3950 KSSLInfoDialog
*kid
= new KSSLInfoDialog(0);
3951 //### This is boilerplate code and it's copied from SlaveInterface.
3952 QStringList sl
= d
->m_ssl_peer_chain
.split('\x01', QString::SkipEmptyParts
);
3953 QList
<QSslCertificate
> certChain
;
3954 bool decodedOk
= true;
3955 foreach (const QString
&s
, sl
) {
3956 certChain
.append(QSslCertificate(s
.toAscii())); //or is it toLocal8Bit or whatever?
3957 if (certChain
.last().isNull()) {
3963 if (decodedOk
|| true /*H4X*/) {
3964 kid
->setSslInfo(certChain
,
3967 d
->m_ssl_protocol_version
,
3969 d
->m_ssl_cipher_used_bits
.toInt(),
3970 d
->m_ssl_cipher_bits
.toInt(),
3971 KSSLInfoDialog::errorsFromString(d
->m_ssl_cert_errors
));
3972 kDebug(7024) << "Showing SSL Info dialog";
3974 kDebug(7024) << "SSL Info dialog closed";
3976 KMessageBox::information(0, i18n("The peer SSL certificate chain "
3977 "appears to be corrupt."),
3982 void KHTMLPart::slotSaveFrame()
3984 KParts::ReadOnlyPart
*frame
= currentFrame();
3988 KUrl
srcURL( frame
->url() );
3990 if ( srcURL
.fileName(KUrl::ObeyTrailingSlash
).isEmpty() )
3991 srcURL
.setFileName( "index" + defaultExtension() );
3993 KIO::MetaData metaData
;
3994 // Referrer unknown?
3995 KHTMLPopupGUIClient::saveURL( d
->m_view
, i18n( "Save Frame As" ), srcURL
, metaData
, "text/html" );
3998 void KHTMLPart::slotSetEncoding(const QString
&enc
)
4000 d
->m_autoDetectLanguage
=KEncodingDetector::None
;
4001 setEncoding( enc
, true);
4004 void KHTMLPart::slotAutomaticDetectionLanguage(KEncodingDetector::AutoDetectScript scri
)
4006 d
->m_autoDetectLanguage
=scri
;
4007 setEncoding( QString(), false );
4010 void KHTMLPart::slotUseStylesheet()
4014 bool autoselect
= (d
->m_paUseStylesheet
->currentItem() == 0);
4015 d
->m_sheetUsed
= autoselect
? QString() : d
->m_paUseStylesheet
->currentText();
4016 d
->m_doc
->updateStyleSelector();
4020 void KHTMLPart::updateActions()
4022 bool frames
= false;
4024 QList
<khtml::ChildFrame
*>::ConstIterator it
= d
->m_frames
.constBegin();
4025 const QList
<khtml::ChildFrame
*>::ConstIterator end
= d
->m_frames
.constEnd();
4026 for (; it
!= end
; ++it
)
4027 if ( (*it
)->m_type
== khtml::ChildFrame::Frame
)
4033 if (d
->m_paViewFrame
)
4034 d
->m_paViewFrame
->setEnabled( frames
);
4035 if (d
->m_paSaveFrame
)
4036 d
->m_paSaveFrame
->setEnabled( frames
);
4039 d
->m_paFind
->setText( i18n( "&Find in Frame..." ) );
4041 d
->m_paFind
->setText( i18n( "&Find..." ) );
4043 KParts::Part
*frame
= 0;
4046 frame
= currentFrame();
4048 bool enableFindAndSelectAll
= true;
4051 enableFindAndSelectAll
= frame
->inherits( "KHTMLPart" );
4053 d
->m_paFind
->setEnabled( enableFindAndSelectAll
);
4054 d
->m_paSelectAll
->setEnabled( enableFindAndSelectAll
);
4056 bool enablePrintFrame
= false;
4060 QObject
*ext
= KParts::BrowserExtension::childObject( frame
);
4062 enablePrintFrame
= ext
->metaObject()->indexOfSlot( "print()" ) != -1;
4065 d
->m_paPrintFrame
->setEnabled( enablePrintFrame
);
4070 if ( d
->m_doc
&& d
->m_doc
->isHTMLDocument() && static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body() && !d
->m_bClearing
)
4071 bgURL
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body()->getAttribute( ATTR_BACKGROUND
).string();
4073 if (d
->m_paSaveBackground
)
4074 d
->m_paSaveBackground
->setEnabled( !bgURL
.isEmpty() );
4076 if ( d
->m_paDebugScript
)
4077 d
->m_paDebugScript
->setEnabled( d
->m_frame
? d
->m_frame
->m_jscript
: 0L );
4080 KParts::LiveConnectExtension
*KHTMLPart::liveConnectExtension( const DOM::NodeImpl
*frame
) {
4081 const ConstFrameIt end
= d
->m_objects
.constEnd();
4082 for(ConstFrameIt it
= d
->m_objects
.constBegin(); it
!= end
; ++it
)
4083 if ((*it
)->m_partContainerElement
== frame
)
4084 return (*it
)->m_liveconnect
;
4088 bool KHTMLPart::requestFrame( DOM::HTMLPartContainerElementImpl
*frame
, const QString
&url
,
4089 const QString
&frameName
, const QStringList
¶ms
, bool isIFrame
)
4091 //kDebug( 6050 ) << this << " requestFrame( ..., " << url << ", " << frameName << " )";
4092 FrameIt it
= d
->m_frames
.find( frameName
);
4093 if ( it
== d
->m_frames
.end() )
4095 khtml::ChildFrame
* child
= new khtml::ChildFrame
;
4096 //kDebug( 6050 ) << "inserting new frame into frame map " << frameName;
4097 child
->m_name
= frameName
;
4098 it
= d
->m_frames
.insert( d
->m_frames
.end(), child
);
4101 (*it
)->m_type
= isIFrame
? khtml::ChildFrame::IFrame
: khtml::ChildFrame::Frame
;
4102 (*it
)->m_partContainerElement
= frame
;
4103 (*it
)->m_params
= params
;
4105 // Support for <frame src="javascript:string">
4106 if ( d
->isJavaScriptURL(url
) )
4108 if ( processObjectRequest(*it
, KUrl("about:blank"), QString("text/html") ) ) {
4109 KHTMLPart
* p
= static_cast<KHTMLPart
*>(static_cast<KParts::ReadOnlyPart
*>((*it
)->m_part
));
4111 // See if we want to replace content with javascript: output..
4112 QVariant res
= p
->executeScript( DOM::Node(),
4113 d
->codeForJavaScriptURL(url
) );
4114 if ( res
.type() == QVariant::String
&& p
->d
->m_redirectURL
.isEmpty() ) {
4116 // We recreated the document, so propagate domain again.
4117 d
->propagateInitialDomainTo( p
);
4118 p
->write( res
.toString() );
4125 KUrl u
= url
.isEmpty() ? KUrl() : completeURL( url
);
4126 return requestObject( *it
, u
);
4129 QString
KHTMLPart::requestFrameName()
4131 return QString::fromLatin1("<!--frame %1-->").arg(d
->m_frameNameId
++);
4134 bool KHTMLPart::requestObject( DOM::HTMLPartContainerElementImpl
*frame
, const QString
&url
,
4135 const QString
&serviceType
, const QStringList
¶ms
)
4137 //kDebug( 6005 ) << this << "frame=" << frame;
4138 khtml::ChildFrame
*child
= new khtml::ChildFrame
;
4139 FrameIt it
= d
->m_objects
.insert( d
->m_objects
.end(), child
);
4140 (*it
)->m_partContainerElement
= frame
;
4141 (*it
)->m_type
= khtml::ChildFrame::Object
;
4142 (*it
)->m_params
= params
;
4144 KParts::OpenUrlArguments args
;
4145 args
.setMimeType(serviceType
);
4146 if (!requestObject( *it
, completeURL( url
), args
) && !(*it
)->m_run
) {
4147 (*it
)->m_bCompleted
= true;
4153 bool KHTMLPart::requestObject( khtml::ChildFrame
*child
, const KUrl
&url
, const KParts::OpenUrlArguments
&_args
,
4154 const KParts::BrowserArguments
& browserArgs
)
4156 if (!checkLinkSecurity(url
))
4158 kDebug(6005) << this << "checkLinkSecurity refused";
4161 if ( child
->m_bPreloaded
)
4163 kDebug(6005) << "preload";
4164 if ( child
->m_partContainerElement
&& child
->m_part
)
4165 child
->m_partContainerElement
->setWidget( child
->m_part
->widget() );
4167 child
->m_bPreloaded
= false;
4171 //kDebug(6005) << "child=" << child << "child->m_part=" << child->m_part;
4173 KParts::OpenUrlArguments
args( _args
);
4176 child
->m_run
->abort();
4178 if ( child
->m_part
&& !args
.reload() && urlcmp( child
->m_part
->url().url(), url
.url(), KUrl::CompareWithoutTrailingSlash
| KUrl::CompareWithoutFragment
) )
4179 args
.setMimeType(child
->m_serviceType
);
4181 child
->m_browserArgs
= browserArgs
;
4182 child
->m_args
= args
;
4183 child
->m_args
.setReload(d
->m_cachePolicy
== KIO::CC_Reload
);
4184 child
->m_serviceName
.clear();
4185 if (!d
->m_referrer
.isEmpty() && !child
->m_args
.metaData().contains( "referrer" ))
4186 child
->m_args
.metaData()["referrer"] = d
->m_referrer
;
4188 child
->m_args
.metaData().insert("PropagateHttpHeader", "true");
4189 child
->m_args
.metaData().insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
4190 child
->m_args
.metaData().insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
4191 child
->m_args
.metaData().insert("main_frame_request",
4192 parentPart() == 0 ? "TRUE":"FALSE");
4193 child
->m_args
.metaData().insert("ssl_was_in_use",
4194 d
->m_ssl_in_use
? "TRUE":"FALSE");
4195 child
->m_args
.metaData().insert("ssl_activate_warnings", "TRUE");
4196 child
->m_args
.metaData().insert("cross-domain", toplevelURL().url());
4198 // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
4199 if ((url
.isEmpty() || url
.url() == "about:blank") && args
.mimeType().isEmpty())
4200 args
.setMimeType(QLatin1String("text/html"));
4202 if ( args
.mimeType().isEmpty() ) {
4203 kDebug(6050) << "Running new KHTMLRun for" << this << "and child=" << child
;
4204 child
->m_run
= new KHTMLRun( this, child
, url
, child
->m_args
, child
->m_browserArgs
, true );
4205 d
->m_bComplete
= false; // ensures we stop it in checkCompleted...
4208 return processObjectRequest( child
, url
, args
.mimeType() );
4212 void KHTMLPart::childLoadFailure( khtml::ChildFrame
*child
)
4214 child
->m_bCompleted
= true;
4215 if ( child
->m_partContainerElement
)
4216 child
->m_partContainerElement
->partLoadingErrorNotify();
4221 bool KHTMLPart::processObjectRequest( khtml::ChildFrame
*child
, const KUrl
&_url
, const QString
&mimetype
)
4223 //kDebug( 6050 ) << "trying to create part for" << mimetype;
4225 // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
4226 // by an emitting frame part (emit openUrlRequest( blahurl, ... ) . A few lines below we delete the part
4227 // though -> the reference becomes invalid -> crash is likely
4230 // khtmlrun called us this way to indicate a loading error
4231 if ( d
->m_onlyLocalReferences
|| ( url
.isEmpty() && mimetype
.isEmpty() ) )
4233 childLoadFailure(child
);
4237 if (child
->m_bNotify
)
4239 child
->m_bNotify
= false;
4240 if ( !child
->m_browserArgs
.lockHistory() )
4241 emit d
->m_extension
->openUrlNotify();
4244 if ( child
->m_serviceType
!= mimetype
|| !child
->m_part
|| (child
->m_run
&& child
->m_run
->serverSuggestsSave()))
4246 // We often get here if we didn't know the mimetype in advance, and had to rely
4247 // on KRun to figure it out. In this case, we let the element check if it wants to
4248 // handle this mimetype itself, for e.g. images.
4249 if ( child
->m_partContainerElement
&&
4250 child
->m_partContainerElement
->mimetypeHandledInternally(mimetype
) ) {
4251 child
->m_bCompleted
= true;
4256 // Before attempting to load a part, check if the user wants that.
4257 // Many don't like getting ZIP files embedded.
4258 // However we don't want to ask for flash and other plugin things..
4259 if ( child
->m_type
!= khtml::ChildFrame::Object
&& child
->m_type
!= khtml::ChildFrame::IFrame
)
4261 QString suggestedFileName
;
4262 int disposition
= 0;
4263 if ( child
->m_run
) {
4264 suggestedFileName
= child
->m_run
->suggestedFileName();
4265 disposition
= (child
->m_run
->serverSuggestsSave()) ? KParts::BrowserRun::AttachmentDisposition
: KParts::BrowserRun::InlineDisposition
;
4268 KParts::BrowserRun::AskSaveResult res
= KParts::BrowserRun::askEmbedOrSave(
4269 url
, mimetype
, suggestedFileName
, disposition
);
4271 case KParts::BrowserRun::Save
:
4272 KHTMLPopupGUIClient::saveURL( widget(), i18n( "Save As" ), url
, child
->m_args
.metaData(), QString(), 0, suggestedFileName
);
4274 case KParts::BrowserRun::Cancel
:
4275 child
->m_bCompleted
= true;
4277 return true; // done
4283 KMimeType::Ptr mime
= KMimeType::mimeType(mimetype
);
4285 // If KHTMLPart can handle the frame, then let's force using it, even
4286 // if the normally preferred part is another one, so that cross-frame
4287 // scripting can work.
4288 if (mime
->is("text/html")
4289 || mime
->is("application/xml")) { // this includes xhtml and svg
4290 child
->m_serviceName
= "khtml";
4294 QStringList dummy
; // the list of servicetypes handled by the part is now unused.
4295 KParts::ReadOnlyPart
*part
= createPart( d
->m_view
->viewport(), this, mimetype
, child
->m_serviceName
, dummy
, child
->m_params
);
4299 childLoadFailure(child
);
4303 part
->setObjectName( child
->m_name
);
4306 if ( child
->m_part
)
4308 if (!qobject_cast
<KHTMLPart
*>(child
->m_part
) && child
->m_jscript
)
4309 child
->m_jscript
->clear();
4310 partManager()->removePart( (KParts::ReadOnlyPart
*)child
->m_part
);
4311 delete (KParts::ReadOnlyPart
*)child
->m_part
;
4312 if (child
->m_liveconnect
) {
4313 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
&)));
4314 child
->m_liveconnect
= 0L;
4318 child
->m_serviceType
= mimetype
;
4319 if ( child
->m_partContainerElement
&& part
->widget() )
4320 child
->m_partContainerElement
->setWidget( part
->widget() );
4322 if ( child
->m_type
!= khtml::ChildFrame::Object
)
4323 partManager()->addPart( part
, false );
4325 // kDebug(6005) << "AH! NO FRAME!!!!!";
4327 child
->m_part
= part
;
4329 if (qobject_cast
<KHTMLPart
*>(part
)) {
4330 static_cast<KHTMLPart
*>(part
)->d
->m_frame
= child
;
4331 } else if (child
->m_partContainerElement
) {
4332 child
->m_liveconnect
= KParts::LiveConnectExtension::childObject(part
);
4333 if (child
->m_liveconnect
)
4334 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
&)));
4336 KParts::StatusBarExtension
*sb
= KParts::StatusBarExtension::childObject(part
);
4338 sb
->setStatusBar( d
->m_statusBarExtension
->statusBar() );
4340 connect( part
, SIGNAL( started( KIO::Job
*) ),
4341 this, SLOT( slotChildStarted( KIO::Job
*) ) );
4342 connect( part
, SIGNAL( completed() ),
4343 this, SLOT( slotChildCompleted() ) );
4344 connect( part
, SIGNAL( completed(bool) ),
4345 this, SLOT( slotChildCompleted(bool) ) );
4346 connect( part
, SIGNAL( setStatusBarText( const QString
& ) ),
4347 this, SIGNAL( setStatusBarText( const QString
& ) ) );
4348 if ( part
->inherits( "KHTMLPart" ) )
4350 connect( this, SIGNAL( completed() ),
4351 part
, SLOT( slotParentCompleted() ) );
4352 connect( this, SIGNAL( completed(bool) ),
4353 part
, SLOT( slotParentCompleted() ) );
4354 // As soon as the child's document is created, we need to set its domain
4355 // (but we do so only once, so it can't be simply done in the child)
4356 connect( part
, SIGNAL( docCreated() ),
4357 this, SLOT( slotChildDocCreated() ) );
4360 child
->m_extension
= KParts::BrowserExtension::childObject( part
);
4362 if ( child
->m_extension
)
4364 connect( child
->m_extension
, SIGNAL( openUrlNotify() ),
4365 d
->m_extension
, SIGNAL( openUrlNotify() ) );
4367 connect( child
->m_extension
, SIGNAL( openUrlRequestDelayed( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
& ) ),
4368 this, SLOT( slotChildURLRequest( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
& ) ) );
4370 connect( child
->m_extension
, SIGNAL( createNewWindow( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
&, const KParts::WindowArgs
&, KParts::ReadOnlyPart
** ) ),
4371 d
->m_extension
, SIGNAL( createNewWindow( const KUrl
&, const KParts::OpenUrlArguments
&, const KParts::BrowserArguments
& , const KParts::WindowArgs
&, KParts::ReadOnlyPart
**) ) );
4373 connect( child
->m_extension
, SIGNAL(popupMenu(QPoint
,KFileItemList
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)),
4374 d
->m_extension
, SIGNAL(popupMenu(QPoint
,KFileItemList
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)) );
4375 connect( child
->m_extension
, SIGNAL(popupMenu(QPoint
,KUrl
,mode_t
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)),
4376 d
->m_extension
, SIGNAL(popupMenu(QPoint
,KUrl
,mode_t
,KParts::OpenUrlArguments
,KParts::BrowserArguments
,KParts::BrowserExtension::PopupFlags
,KParts::BrowserExtension::ActionGroupMap
)) );
4378 connect( child
->m_extension
, SIGNAL( infoMessage( const QString
& ) ),
4379 d
->m_extension
, SIGNAL( infoMessage( const QString
& ) ) );
4381 connect( child
->m_extension
, SIGNAL( requestFocus( KParts::ReadOnlyPart
* ) ),
4382 this, SLOT( slotRequestFocus( KParts::ReadOnlyPart
* ) ) );
4384 child
->m_extension
->setBrowserInterface( d
->m_extension
->browserInterface() );
4387 else if ( child
->m_partContainerElement
&& child
->m_part
&&
4388 child
->m_partContainerElement
->childWidget() != child
->m_part
->widget() )
4389 child
->m_partContainerElement
->setWidget( child
->m_part
->widget() );
4391 checkEmitLoadEvent();
4392 // Some JS code in the load event may have destroyed the part
4393 // In that case, abort
4394 if ( !child
->m_part
)
4397 if ( child
->m_bPreloaded
)
4399 if ( child
->m_partContainerElement
&& child
->m_part
)
4400 child
->m_partContainerElement
->setWidget( child
->m_part
->widget() );
4402 child
->m_bPreloaded
= false;
4406 child
->m_args
.setReload(d
->m_cachePolicy
== KIO::CC_Reload
);
4408 // make sure the part has a way to find out about the mimetype.
4409 // we actually set it in child->m_args in requestObject already,
4410 // but it's useless if we had to use a KHTMLRun instance, as the
4411 // point the run object is to find out exactly the mimetype.
4412 child
->m_args
.setMimeType(mimetype
);
4414 // if not a frame set child as completed
4415 child
->m_bCompleted
= child
->m_type
== khtml::ChildFrame::Object
;
4417 if ( child
->m_part
) {
4418 child
->m_part
->setArguments( child
->m_args
);
4420 if ( child
->m_extension
) {
4421 child
->m_extension
->setBrowserArguments( child
->m_browserArgs
);
4424 if(url
.protocol() == "javascript" || url
.url() == "about:blank") {
4425 if (!child
->m_part
->inherits("KHTMLPart"))
4428 KHTMLPart
* p
= static_cast<KHTMLPart
*>(static_cast<KParts::ReadOnlyPart
*>(child
->m_part
));
4431 if (d
->m_doc
&& p
->d
->m_doc
)
4432 p
->d
->m_doc
->setBaseURL(d
->m_doc
->baseURL());
4434 // We may have to re-propagate the domain here if we go here due to navigation
4435 d
->propagateInitialDomainTo(p
);
4437 if (!url
.url().startsWith("about:")) {
4438 p
->write(url
.path());
4441 // we need a body element. testcase: <iframe id="a"></iframe><script>alert(a.document.body);</script>
4442 p
->write("<HTML><TITLE></TITLE><BODY></BODY></HTML>");
4447 else if ( !url
.isEmpty() )
4449 //kDebug( 6050 ) << "opening" << url << "in frame" << child->m_part;
4450 bool b
= child
->m_part
->openUrl( url
);
4451 if (child
->m_bCompleted
)
4457 child
->m_bCompleted
= true;
4463 KParts::ReadOnlyPart
*KHTMLPart::createPart( QWidget
*parentWidget
,
4464 QObject
*parent
, const QString
&mimetype
,
4465 QString
&serviceName
, QStringList
&serviceTypes
,
4466 const QStringList
¶ms
)
4469 if ( !serviceName
.isEmpty() )
4470 constr
.append( QString::fromLatin1( "DesktopEntryName == '%1'" ).arg( serviceName
) );
4472 KService::List offers
= KMimeTypeTrader::self()->query( mimetype
, "KParts/ReadOnlyPart", constr
);
4474 if ( offers
.isEmpty() ) {
4475 int pos
= mimetype
.indexOf( "-plugin" );
4478 QString stripped_mime
= mimetype
.left( pos
);
4479 offers
= KMimeTypeTrader::self()->query( stripped_mime
, "KParts/ReadOnlyPart", constr
);
4480 if ( offers
.isEmpty() )
4484 KService::List::ConstIterator it
= offers
.constBegin();
4485 const KService::List::ConstIterator itEnd
= offers
.constEnd();
4486 for ( ; it
!= itEnd
; ++it
)
4488 KService::Ptr service
= (*it
);
4490 KPluginLoader
loader( *service
, KHTMLGlobal::componentData() );
4491 KPluginFactory
* const factory
= loader
.factory();
4493 // Turn params into a QVariantList as expected by KPluginFactory
4494 QVariantList variantlist
;
4495 Q_FOREACH(const QString
& str
, params
)
4496 variantlist
<< QVariant(str
);
4498 if ( service
->serviceTypes().contains( "Browser/View" ) )
4499 variantlist
<< QString("Browser/View");
4501 KParts::ReadOnlyPart
* part
= factory
->create
<KParts::ReadOnlyPart
>(parentWidget
, parent
, QString(), variantlist
);
4503 serviceTypes
= service
->serviceTypes();
4504 serviceName
= service
->name();
4508 // TODO KMessageBox::error and i18n, like in KonqFactory::createView?
4509 kWarning() << QString("There was an error loading the module %1.\nThe diagnostics is:\n%2")
4510 .arg(service
->name()).arg(loader
.errorString());
4516 KParts::PartManager
*KHTMLPart::partManager()
4518 if ( !d
->m_manager
&& d
->m_view
)
4520 d
->m_manager
= new KParts::PartManager( d
->m_view
->topLevelWidget(), this );
4521 d
->m_manager
->setObjectName( "khtml part manager" );
4522 d
->m_manager
->setAllowNestedParts( true );
4523 connect( d
->m_manager
, SIGNAL( activePartChanged( KParts::Part
* ) ),
4524 this, SLOT( slotActiveFrameChanged( KParts::Part
* ) ) );
4525 connect( d
->m_manager
, SIGNAL( partRemoved( KParts::Part
* ) ),
4526 this, SLOT( slotPartRemoved( KParts::Part
* ) ) );
4529 return d
->m_manager
;
4532 void KHTMLPart::submitFormAgain()
4534 disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
4535 if( d
->m_doc
&& !d
->m_doc
->parsing() && d
->m_submitForm
)
4536 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
);
4538 delete d
->m_submitForm
;
4539 d
->m_submitForm
= 0;
4542 void KHTMLPart::submitFormProxy( const char *action
, const QString
&url
, const QByteArray
&formData
, const QString
&_target
, const QString
& contentType
, const QString
& boundary
)
4544 submitForm(action
, url
, formData
, _target
, contentType
, boundary
);
4547 void KHTMLPart::submitForm( const char *action
, const QString
&url
, const QByteArray
&formData
, const QString
&_target
, const QString
& contentType
, const QString
& boundary
)
4549 kDebug(6000) << this << "target=" << _target
<< "url=" << url
;
4550 if (d
->m_formNotification
== KHTMLPart::Only
) {
4551 emit
formSubmitNotification(action
, url
, formData
, _target
, contentType
, boundary
);
4553 } else if (d
->m_formNotification
== KHTMLPart::Before
) {
4554 emit
formSubmitNotification(action
, url
, formData
, _target
, contentType
, boundary
);
4557 KUrl u
= completeURL( url
);
4561 // ### ERROR HANDLING!
4565 // Form security checks
4568 * If these form security checks are still in this place in a month or two
4569 * I'm going to simply delete them.
4572 /* This is separate for a reason. It has to be _before_ all script, etc,
4573 * AND I don't want to break anything that uses checkLinkSecurity() in
4577 if (!d
->m_submitForm
) {
4578 if (u
.protocol() != "https" && u
.protocol() != "mailto") {
4579 if (d
->m_ssl_in_use
) { // Going from SSL -> nonSSL
4580 int rc
= KMessageBox::warningContinueCancel(NULL
, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted."
4581 "\nA third party may be able to intercept and view this information."
4582 "\nAre you sure you wish to continue?"),
4583 i18n("Network Transmission"),KGuiItem(i18n("&Send Unencrypted")));
4584 if (rc
== KMessageBox::Cancel
)
4586 } else { // Going from nonSSL -> nonSSL
4587 KSSLSettings
kss(true);
4588 if (kss
.warnOnUnencrypted()) {
4589 int rc
= KMessageBox::warningContinueCancel(NULL
,
4590 i18n("Warning: Your data is about to be transmitted across the network unencrypted."
4591 "\nAre you sure you wish to continue?"),
4592 i18n("Network Transmission"),
4593 KGuiItem(i18n("&Send Unencrypted")),
4594 KStandardGuiItem::cancel(),
4595 "WarnOnUnencryptedForm");
4596 // Move this setting into KSSL instead
4597 QString grpNotifMsgs
= QLatin1String("Notification Messages");
4598 KConfigGroup
cg( KGlobal::config(), grpNotifMsgs
);
4600 if (!cg
.readEntry("WarnOnUnencryptedForm", true)) {
4601 cg
.deleteEntry("WarnOnUnencryptedForm");
4603 kss
.setWarnOnUnencrypted(false);
4606 if (rc
== KMessageBox::Cancel
)
4612 if (u
.protocol() == "mailto") {
4613 int rc
= KMessageBox::warningContinueCancel(NULL
,
4614 i18n("This site is attempting to submit form data via email.\n"
4615 "Do you want to continue?"),
4616 i18n("Network Transmission"),
4617 KGuiItem(i18n("&Send Email")),
4618 KStandardGuiItem::cancel(),
4619 "WarnTriedEmailSubmit");
4621 if (rc
== KMessageBox::Cancel
) {
4627 // End form security checks
4630 QString urlstring
= u
.url();
4632 if ( d
->isJavaScriptURL(urlstring
) ) {
4633 crossFrameExecuteScript( _target
, d
->codeForJavaScriptURL(urlstring
) );
4637 if (!checkLinkSecurity(u
,
4638 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>" ),
4642 // OK. We're actually going to submit stuff. Clear any redirections,
4643 // we should win over them
4644 d
->clearRedirection();
4646 KParts::OpenUrlArguments args
;
4648 if (!d
->m_referrer
.isEmpty())
4649 args
.metaData()["referrer"] = d
->m_referrer
;
4651 args
.metaData().insert("PropagateHttpHeader", "true");
4652 args
.metaData().insert("ssl_parent_ip", d
->m_ssl_parent_ip
);
4653 args
.metaData().insert("ssl_parent_cert", d
->m_ssl_parent_cert
);
4654 args
.metaData().insert("main_frame_request",
4655 parentPart() == 0 ? "TRUE":"FALSE");
4656 args
.metaData().insert("ssl_was_in_use", d
->m_ssl_in_use
? "TRUE":"FALSE");
4657 args
.metaData().insert("ssl_activate_warnings", "TRUE");
4658 //WABA: When we post a form we should treat it as the main url
4659 //the request should never be considered cross-domain
4660 //args.metaData().insert("cross-domain", toplevelURL().url());
4661 KParts::BrowserArguments browserArgs
;
4662 browserArgs
.frameName
= _target
.isEmpty() ? d
->m_doc
->baseTarget() : _target
;
4664 // Handle mailto: forms
4665 if (u
.protocol() == "mailto") {
4666 // 1) Check for attach= and strip it
4667 QString q
= u
.query().mid(1);
4668 QStringList nvps
= q
.split("&");
4669 bool triedToAttach
= false;
4671 QStringList::Iterator nvp
= nvps
.begin();
4672 const QStringList::Iterator nvpEnd
= nvps
.end();
4674 // cannot be a for loop as if something is removed we don't want to do ++nvp, as
4675 // remove returns an iterator pointing to the next item
4677 while (nvp
!= nvpEnd
) {
4678 const QStringList pair
= (*nvp
).split("=");
4679 if (pair
.count() >= 2) {
4680 if (pair
.first().toLower() == "attach") {
4681 nvp
= nvps
.erase(nvp
);
4682 triedToAttach
= true;
4692 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");
4696 if (contentType
.toLower() == "multipart/form-data") {
4697 // FIXME: is this correct? I suspect not
4698 bodyEnc
= QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData
.data(),
4700 } else if (contentType
.toLower() == "text/plain") {
4701 // Convention seems to be to decode, and s/&/\n/
4702 QString tmpbody
= QString::fromLatin1(formData
.data(),
4704 tmpbody
.replace(QRegExp("[&]"), "\n");
4705 tmpbody
.replace(QRegExp("[+]"), " ");
4706 tmpbody
= KUrl::fromPercentEncoding(tmpbody
.toLatin1()); // Decode the rest of it
4707 bodyEnc
= QLatin1String( KUrl::toPercentEncoding(tmpbody
) ); // Recode for the URL
4709 bodyEnc
= QLatin1String( KUrl::toPercentEncoding(QString::fromLatin1(formData
.data(),
4710 formData
.size())) );
4713 nvps
.append(QString("body=%1").arg(bodyEnc
));
4718 if ( strcmp( action
, "get" ) == 0 ) {
4719 if (u
.protocol() != "mailto")
4720 u
.setQuery( QString::fromLatin1( formData
.data(), formData
.size() ) );
4721 browserArgs
.setDoPost( false );
4724 browserArgs
.postData
= formData
;
4725 browserArgs
.setDoPost( true );
4727 // construct some user headers if necessary
4728 if (contentType
.isNull() || contentType
== "application/x-www-form-urlencoded")
4729 browserArgs
.setContentType( "Content-Type: application/x-www-form-urlencoded" );
4730 else // contentType must be "multipart/form-data"
4731 browserArgs
.setContentType( "Content-Type: " + contentType
+ "; boundary=" + boundary
);
4734 if ( d
->m_doc
->parsing() || d
->m_runningScripts
> 0 ) {
4735 if( d
->m_submitForm
) {
4736 kDebug(6000) << "ABORTING!";
4739 d
->m_submitForm
= new KHTMLPartPrivate::SubmitForm
;
4740 d
->m_submitForm
->submitAction
= action
;
4741 d
->m_submitForm
->submitUrl
= url
;
4742 d
->m_submitForm
->submitFormData
= formData
;
4743 d
->m_submitForm
->target
= _target
;
4744 d
->m_submitForm
->submitContentType
= contentType
;
4745 d
->m_submitForm
->submitBoundary
= boundary
;
4746 connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
4750 emit d
->m_extension
->openUrlRequest( u
, args
, browserArgs
);
4754 void KHTMLPart::popupMenu( const QString
&linkUrl
)
4758 KParts::OpenUrlArguments args
;
4759 KParts::BrowserArguments browserArgs
;
4761 KParts::BrowserExtension::PopupFlags itemflags
=KParts::BrowserExtension::ShowBookmark
| KParts::BrowserExtension::ShowReload
;
4763 if ( linkUrl
.isEmpty() ) { // click on background
4764 KHTMLPart
* khtmlPart
= this;
4765 while ( khtmlPart
->parentPart() )
4767 khtmlPart
=khtmlPart
->parentPart();
4769 popupURL
= khtmlPart
->url();
4770 referrer
= khtmlPart
->pageReferrer();
4772 itemflags
= KParts::BrowserExtension::ShowTextSelectionItems
;
4774 itemflags
|= KParts::BrowserExtension::ShowNavigationItems
;
4775 } else { // click on link
4776 popupURL
= completeURL( linkUrl
);
4777 linkKUrl
= popupURL
;
4778 referrer
= this->referrer();
4779 itemflags
|= KParts::BrowserExtension::IsLink
;
4781 if (!(d
->m_strSelectedURLTarget
).isEmpty() &&
4782 (d
->m_strSelectedURLTarget
.toLower() != "_top") &&
4783 (d
->m_strSelectedURLTarget
.toLower() != "_self") &&
4784 (d
->m_strSelectedURLTarget
.toLower() != "_parent")) {
4785 if (d
->m_strSelectedURLTarget
.toLower() == "_blank")
4786 browserArgs
.setForcesNewWindow(true);
4788 KHTMLPart
*p
= this;
4789 while (p
->parentPart())
4790 p
= p
->parentPart();
4791 if (!p
->frameExists(d
->m_strSelectedURLTarget
))
4792 browserArgs
.setForcesNewWindow(true);
4797 // Danger, Will Robinson. The Popup might stay around for a much
4798 // longer time than KHTMLPart. Deal with it.
4799 KHTMLPopupGUIClient
* client
= new KHTMLPopupGUIClient( this, linkKUrl
);
4800 QPointer
<QObject
> guard( client
);
4802 QString mimetype
= QLatin1String( "text/html" );
4803 args
.metaData()["referrer"] = referrer
;
4805 if (!linkUrl
.isEmpty()) // over a link
4807 if (popupURL
.isLocalFile()) // safe to do this
4809 mimetype
= KMimeType::findByUrl(popupURL
,0,true,false)->name();
4811 else // look at "extension" of link
4813 const QString
fname(popupURL
.fileName(KUrl::ObeyTrailingSlash
));
4814 if (!fname
.isEmpty() && !popupURL
.hasRef() && popupURL
.query().isEmpty())
4816 KMimeType::Ptr pmt
= KMimeType::findByPath(fname
,0,true);
4818 // Further check for mime types guessed from the extension which,
4819 // on a web page, are more likely to be a script delivering content
4820 // of undecidable type. If the mime type from the extension is one
4821 // of these, don't use it. Retain the original type 'text/html'.
4822 if (pmt
->name() != KMimeType::defaultMimeType() &&
4823 !pmt
->is("application/x-perl") &&
4824 !pmt
->is("application/x-perl-module") &&
4825 !pmt
->is("application/x-php") &&
4826 !pmt
->is("application/x-python-bytecode") &&
4827 !pmt
->is("application/x-python") &&
4828 !pmt
->is("application/x-shellscript"))
4829 mimetype
= pmt
->name();
4834 args
.setMimeType(mimetype
);
4836 emit d
->m_extension
->popupMenu( QCursor::pos(), popupURL
, S_IFREG
/*always a file*/,
4837 args
, browserArgs
, itemflags
,
4838 client
->actionGroups() );
4840 if ( !guard
.isNull() ) {
4842 emit
popupMenu(linkUrl
, QCursor::pos());
4843 d
->m_strSelectedURL
.clear();
4844 d
->m_strSelectedURLTarget
.clear();
4848 void KHTMLPart::slotParentCompleted()
4850 //kDebug(6050) << this;
4851 if ( !d
->m_redirectURL
.isEmpty() && !d
->m_redirectionTimer
.isActive() )
4853 //kDebug(6050) << this << ": starting timer for child redirection -> " << d->m_redirectURL;
4854 d
->m_redirectionTimer
.setSingleShot( true );
4855 d
->m_redirectionTimer
.start( qMax(0, 1000 * d
->m_delayRedirect
) );
4859 void KHTMLPart::slotChildStarted( KIO::Job
*job
)
4861 khtml::ChildFrame
*child
= frame( sender() );
4865 child
->m_bCompleted
= false;
4867 if ( d
->m_bComplete
)
4870 // WABA: Looks like this belongs somewhere else
4871 if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
4873 emit d
->m_extension
->openURLNotify();
4876 d
->m_bComplete
= false;
4877 emit
started( job
);
4881 void KHTMLPart::slotChildCompleted()
4883 slotChildCompleted( false );
4886 void KHTMLPart::slotChildCompleted( bool pendingAction
)
4888 khtml::ChildFrame
*child
= frame( sender() );
4891 kDebug(6050) << this << "child=" << child
<< "m_partContainerElement=" << child
->m_partContainerElement
;
4892 child
->m_bCompleted
= true;
4893 child
->m_bPendingRedirection
= pendingAction
;
4894 child
->m_args
= KParts::OpenUrlArguments();
4895 child
->m_browserArgs
= KParts::BrowserArguments();
4896 // dispatch load event
4897 if (!qobject_cast
<KHTMLPart
*>(child
->m_part
))
4898 QTimer::singleShot(0, child
->m_partContainerElement
, SLOT(slotEmitLoadEvent()));
4903 void KHTMLPart::slotChildDocCreated()
4905 // Set domain to the frameset's domain
4906 // This must only be done when loading the frameset initially (#22039),
4907 // not when following a link in a frame (#44162).
4908 if (KHTMLPart
* htmlFrame
= qobject_cast
<KHTMLPart
*>(sender()))
4909 d
->propagateInitialDomainTo( htmlFrame
);
4911 // So it only happens once
4912 disconnect( sender(), SIGNAL( docCreated() ), this, SLOT( slotChildDocCreated() ) );
4915 void KHTMLPartPrivate::propagateInitialDomainTo(KHTMLPart
* kid
)
4917 // This method is used to propagate our domain information for
4918 // child frames, potentially widening to have less periods, and also
4919 // to provide a domain for about: or JavaScript: URLs altogether.
4920 // Note that DocumentImpl:;setDomain does the checking.
4921 if ( m_doc
&& kid
->d
->m_doc
)
4922 kid
->d
->m_doc
->setDomain( m_doc
->domain() );
4925 void KHTMLPart::slotChildURLRequest( const KUrl
&url
, const KParts::OpenUrlArguments
& args
, const KParts::BrowserArguments
&browserArgs
)
4927 khtml::ChildFrame
*child
= frame( sender()->parent() );
4928 KHTMLPart
*callingHtmlPart
= const_cast<KHTMLPart
*>(dynamic_cast<const KHTMLPart
*>(sender()->parent()));
4930 // TODO: handle child target correctly! currently the script are always executed for the parent
4931 QString urlStr
= url
.url();
4932 if ( d
->isJavaScriptURL(urlStr
) ) {
4933 executeScript( DOM::Node(), d
->codeForJavaScriptURL(urlStr
) );
4937 QString frameName
= browserArgs
.frameName
.toLower();
4938 if ( !frameName
.isEmpty() ) {
4939 if ( frameName
== QLatin1String( "_top" ) )
4941 emit d
->m_extension
->openUrlRequest( url
, args
, browserArgs
);
4944 else if ( frameName
== QLatin1String( "_blank" ) )
4946 emit d
->m_extension
->createNewWindow( url
, args
, browserArgs
);
4949 else if ( frameName
== QLatin1String( "_parent" ) )
4951 KParts::BrowserArguments
newBrowserArgs( browserArgs
);
4952 newBrowserArgs
.frameName
.clear();
4953 emit d
->m_extension
->openUrlRequest( url
, args
, newBrowserArgs
);
4956 else if ( frameName
!= QLatin1String( "_self" ) )
4958 khtml::ChildFrame
*_frame
= recursiveFrameRequest( callingHtmlPart
, url
, args
, browserArgs
);
4962 emit d
->m_extension
->openUrlRequest( url
, args
, browserArgs
);
4970 if ( child
&& child
->m_type
!= khtml::ChildFrame::Object
) {
4971 // Inform someone that we are about to show something else.
4972 child
->m_bNotify
= true;
4973 requestObject( child
, url
, args
, browserArgs
);
4974 } else if ( frameName
== "_self" ) // this is for embedded objects (via <object>) which want to replace the current document
4976 KParts::BrowserArguments
newBrowserArgs( browserArgs
);
4977 newBrowserArgs
.frameName
.clear();
4978 emit d
->m_extension
->openUrlRequest( url
, args
, newBrowserArgs
);
4982 void KHTMLPart::slotRequestFocus( KParts::ReadOnlyPart
* )
4984 emit d
->m_extension
->requestFocus(this);
4987 khtml::ChildFrame
*KHTMLPart::frame( const QObject
*obj
)
4989 assert( obj
->inherits( "KParts::ReadOnlyPart" ) );
4990 const KParts::ReadOnlyPart
* const part
= static_cast<const KParts::ReadOnlyPart
*>( obj
);
4992 FrameIt it
= d
->m_frames
.begin();
4993 const FrameIt end
= d
->m_frames
.end();
4994 for (; it
!= end
; ++it
)
4995 if ( (KParts::ReadOnlyPart
*)(*it
)->m_part
== part
)
4998 FrameIt oi
= d
->m_objects
.begin();
4999 const FrameIt oiEnd
= d
->m_objects
.end();
5000 for (; oi
!= oiEnd
; ++oi
)
5001 if ( (KParts::ReadOnlyPart
*)(*oi
)->m_part
== part
)
5007 //#define DEBUG_FINDFRAME
5009 bool KHTMLPart::checkFrameAccess(KHTMLPart
*callingHtmlPart
)
5011 if (callingHtmlPart
== this)
5012 return true; // trivial
5014 if (!xmlDocImpl()) {
5015 #ifdef DEBUG_FINDFRAME
5016 kDebug(6050) << "Empty part" << this << "URL = " << url();
5018 return false; // we are empty?
5021 // now compare the domains
5022 if (callingHtmlPart
&& callingHtmlPart
->xmlDocImpl() && xmlDocImpl()) {
5023 DOM::DOMString actDomain
= callingHtmlPart
->xmlDocImpl()->domain();
5024 DOM::DOMString destDomain
= xmlDocImpl()->domain();
5026 #ifdef DEBUG_FINDFRAME
5027 kDebug(6050) << "actDomain =" << actDomain
.string() << "destDomain =" << destDomain
.string();
5030 if (actDomain
== destDomain
)
5033 #ifdef DEBUG_FINDFRAME
5036 kDebug(6050) << "Unknown part/domain" << callingHtmlPart
<< "tries to access part" << this;
5043 KHTMLPart::findFrameParent( KParts::ReadOnlyPart
*callingPart
, const QString
&f
, khtml::ChildFrame
**childFrame
)
5045 #ifdef DEBUG_FINDFRAME
5046 kDebug(6050) << this << "URL =" << url() << "name =" << name() << "findFrameParent(" << f
<< ")";
5049 KHTMLPart
* const callingHtmlPart
= dynamic_cast<KHTMLPart
*>(callingPart
);
5051 if (!checkFrameAccess(callingHtmlPart
))
5054 if (!childFrame
&& !parentPart() && (objectName() == f
))
5057 FrameIt it
= d
->m_frames
.find( f
);
5058 const FrameIt end
= d
->m_frames
.end();
5061 #ifdef DEBUG_FINDFRAME
5062 kDebug(6050) << "FOUND!";
5069 it
= d
->m_frames
.begin();
5070 for (; it
!= end
; ++it
)
5072 KParts::ReadOnlyPart
* const p
= (*it
)->m_part
;
5073 if ( p
&& p
->inherits( "KHTMLPart" ))
5075 KHTMLPart
* const frameParent
= static_cast<KHTMLPart
*>(p
)->findFrameParent(callingPart
, f
, childFrame
);
5084 KHTMLPart
*KHTMLPart::findFrame( const QString
&f
)
5086 khtml::ChildFrame
*childFrame
;
5087 KHTMLPart
*parentFrame
= findFrameParent(this, f
, &childFrame
);
5090 KParts::ReadOnlyPart
*p
= childFrame
->m_part
;
5091 if ( p
&& p
->inherits( "KHTMLPart" ))
5092 return static_cast<KHTMLPart
*>(p
);
5097 KParts::ReadOnlyPart
*KHTMLPart::findFramePart(const QString
&f
)
5099 khtml::ChildFrame
*childFrame
;
5100 return findFrameParent(this, f
, &childFrame
) ? static_cast<KParts::ReadOnlyPart
*>(childFrame
->m_part
) : 0L;
5103 KParts::ReadOnlyPart
*KHTMLPart::currentFrame() const
5105 KParts::ReadOnlyPart
* part
= (KParts::ReadOnlyPart
*)(this);
5106 // Find active part in our frame manager, in case we are a frameset
5107 // and keep doing that (in case of nested framesets).
5108 // Just realized we could also do this recursively, calling part->currentFrame()...
5109 while ( part
&& part
->inherits("KHTMLPart") &&
5110 static_cast<KHTMLPart
*>(part
)->d
->m_frames
.count() > 0 ) {
5111 KHTMLPart
* frameset
= static_cast<KHTMLPart
*>(part
);
5112 part
= static_cast<KParts::ReadOnlyPart
*>(frameset
->partManager()->activePart());
5113 if ( !part
) return frameset
;
5118 bool KHTMLPart::frameExists( const QString
&frameName
)
5120 FrameIt it
= d
->m_frames
.find( frameName
);
5121 if ( it
== d
->m_frames
.end() )
5124 // WABA: We only return true if the child actually has a frame
5125 // set. Otherwise we might find our preloaded-selve.
5126 // This happens when we restore the frameset.
5127 return (!(*it
)->m_partContainerElement
.isNull());
5130 KJSProxy
*KHTMLPart::framejScript(KParts::ReadOnlyPart
*framePart
)
5132 KHTMLPart
* const kp
= qobject_cast
<KHTMLPart
*>(framePart
);
5134 return kp
->jScript();
5136 FrameIt it
= d
->m_frames
.begin();
5137 const FrameIt itEnd
= d
->m_frames
.end();
5139 for (; it
!= itEnd
; ++it
)
5140 if (framePart
== (*it
)->m_part
) {
5141 if (!(*it
)->m_jscript
)
5143 return (*it
)->m_jscript
;
5148 KHTMLPart
*KHTMLPart::parentPart()
5150 return qobject_cast
<KHTMLPart
*>( parent() );
5153 khtml::ChildFrame
*KHTMLPart::recursiveFrameRequest( KHTMLPart
*callingHtmlPart
, const KUrl
&url
,
5154 const KParts::OpenUrlArguments
&args
,
5155 const KParts::BrowserArguments
&browserArgs
, bool callParent
)
5157 #ifdef DEBUG_FINDFRAME
5158 kDebug( 6050 ) << this << "frame = " << args
.frameName
<< "url = " << url
;
5160 khtml::ChildFrame
*childFrame
;
5161 KHTMLPart
*childPart
= findFrameParent(callingHtmlPart
, browserArgs
.frameName
, &childFrame
);
5164 if (childPart
== this)
5167 childPart
->requestObject( childFrame
, url
, args
, browserArgs
);
5171 if ( parentPart() && callParent
)
5173 khtml::ChildFrame
*res
= parentPart()->recursiveFrameRequest( callingHtmlPart
, url
, args
, browserArgs
, callParent
);
5176 parentPart()->requestObject( res
, url
, args
, browserArgs
);
5182 #ifdef DEBUG_SAVESTATE
5183 static int s_saveStateIndentLevel
= 0;
5186 void KHTMLPart::saveState( QDataStream
&stream
)
5188 #ifdef DEBUG_SAVESTATE
5189 QString indent
= QString().leftJustified( s_saveStateIndentLevel
* 4, ' ' );
5190 const int indentLevel
= s_saveStateIndentLevel
++;
5191 kDebug( 6050 ) << indent
<< "saveState this=" << this << " '" << objectName() << "' saving URL " << url().url();
5194 stream
<< url() << (qint32
)d
->m_view
->contentsX() << (qint32
)d
->m_view
->contentsY()
5195 << (qint32
) d
->m_view
->contentsWidth() << (qint32
) d
->m_view
->contentsHeight() << (qint32
) d
->m_view
->marginWidth() << (qint32
) d
->m_view
->marginHeight();
5197 // save link cursor position
5198 int focusNodeNumber
;
5199 if (!d
->m_focusNodeRestored
)
5200 focusNodeNumber
= d
->m_focusNodeNumber
;
5201 else if (d
->m_doc
&& d
->m_doc
->focusNode())
5202 focusNodeNumber
= d
->m_doc
->nodeAbsIndex(d
->m_doc
->focusNode());
5204 focusNodeNumber
= -1;
5205 stream
<< focusNodeNumber
;
5207 // Save the doc's cache id.
5208 stream
<< d
->m_cacheId
;
5210 // Save the state of the document (Most notably the state of any forms)
5211 QStringList docState
;
5214 docState
= d
->m_doc
->docState();
5216 stream
<< d
->m_encoding
<< d
->m_sheetUsed
<< docState
;
5218 stream
<< d
->m_zoomFactor
;
5219 stream
<< d
->m_fontScaleFactor
;
5221 stream
<< d
->m_httpHeaders
;
5222 stream
<< d
->m_pageServices
;
5223 stream
<< d
->m_pageReferrer
;
5226 stream
<< d
->m_ssl_in_use
5227 << d
->m_ssl_peer_chain
5230 << d
->m_ssl_protocol_version
5231 << d
->m_ssl_cipher_used_bits
5232 << d
->m_ssl_cipher_bits
5233 << d
->m_ssl_cert_errors
5234 << d
->m_ssl_parent_ip
5235 << d
->m_ssl_parent_cert
;
5238 QStringList frameNameLst
, frameServiceTypeLst
, frameServiceNameLst
;
5239 KUrl::List frameURLLst
;
5240 QList
<QByteArray
> frameStateBufferLst
;
5241 QList
<int> frameTypeLst
;
5243 ConstFrameIt it
= d
->m_frames
.constBegin();
5244 const ConstFrameIt end
= d
->m_frames
.constEnd();
5245 for (; it
!= end
; ++it
)
5247 if ( !(*it
)->m_part
)
5250 frameNameLst
<< (*it
)->m_name
;
5251 frameServiceTypeLst
<< (*it
)->m_serviceType
;
5252 frameServiceNameLst
<< (*it
)->m_serviceName
;
5253 frameURLLst
<< (*it
)->m_part
->url();
5256 QDataStream
frameStream( &state
, QIODevice::WriteOnly
);
5258 if ( (*it
)->m_extension
)
5259 (*it
)->m_extension
->saveState( frameStream
);
5261 frameStateBufferLst
<< state
;
5263 frameTypeLst
<< int( (*it
)->m_type
);
5267 stream
<< (quint32
) frameNameLst
.count();
5268 stream
<< frameNameLst
<< frameServiceTypeLst
<< frameServiceNameLst
<< frameURLLst
<< frameStateBufferLst
<< frameTypeLst
;
5269 #ifdef DEBUG_SAVESTATE
5270 s_saveStateIndentLevel
= indentLevel
;
5274 void KHTMLPart::restoreState( QDataStream
&stream
)
5277 qint32 xOffset
, yOffset
, wContents
, hContents
, mWidth
, mHeight
;
5279 QStringList frameNames
, frameServiceTypes
, docState
, frameServiceNames
;
5280 QList
<int> frameTypes
;
5281 KUrl::List frameURLs
;
5282 QList
<QByteArray
> frameStateBuffers
;
5284 QString encoding
, sheetUsed
;
5285 long old_cacheId
= d
->m_cacheId
;
5287 stream
>> u
>> xOffset
>> yOffset
>> wContents
>> hContents
>> mWidth
>> mHeight
;
5289 d
->m_view
->setMarginWidth( mWidth
);
5290 d
->m_view
->setMarginHeight( mHeight
);
5292 // restore link cursor position
5293 // nth node is active. value is set in checkCompleted()
5294 stream
>> d
->m_focusNodeNumber
;
5295 d
->m_focusNodeRestored
= false;
5297 stream
>> d
->m_cacheId
;
5299 stream
>> encoding
>> sheetUsed
>> docState
;
5301 d
->m_encoding
= encoding
;
5302 d
->m_sheetUsed
= sheetUsed
;
5305 stream
>> zoomFactor
;
5306 setZoomFactor(zoomFactor
);
5308 int fontScaleFactor
;
5309 stream
>> fontScaleFactor
;
5310 setFontScaleFactor(fontScaleFactor
);
5312 stream
>> d
->m_httpHeaders
;
5313 stream
>> d
->m_pageServices
;
5314 stream
>> d
->m_pageReferrer
;
5317 stream
>> d
->m_ssl_in_use
5318 >> d
->m_ssl_peer_chain
5321 >> d
->m_ssl_protocol_version
5322 >> d
->m_ssl_cipher_used_bits
5323 >> d
->m_ssl_cipher_bits
5324 >> d
->m_ssl_cert_errors
5325 >> d
->m_ssl_parent_ip
5326 >> d
->m_ssl_parent_cert
;
5328 setPageSecurity( d
->m_ssl_in_use
? Encrypted
: NotCrypted
);
5330 stream
>> frameCount
>> frameNames
>> frameServiceTypes
>> frameServiceNames
5331 >> frameURLs
>> frameStateBuffers
>> frameTypes
;
5333 d
->m_bComplete
= false;
5334 d
->m_bLoadEventEmitted
= false;
5336 // kDebug( 6050 ) << "docState.count() = " << docState.count();
5337 // kDebug( 6050 ) << "m_url " << url().url() << " <-> " << u.url();
5338 // kDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount;
5340 if (d
->m_cacheId
== old_cacheId
)
5343 d
->m_redirectionTimer
.stop();
5345 FrameIt fIt
= d
->m_frames
.begin();
5346 const FrameIt fEnd
= d
->m_frames
.end();
5348 for (; fIt
!= fEnd
; ++fIt
)
5349 (*fIt
)->m_bCompleted
= false;
5351 fIt
= d
->m_frames
.begin();
5353 QStringList::ConstIterator fNameIt
= frameNames
.constBegin();
5354 QStringList::ConstIterator fServiceTypeIt
= frameServiceTypes
.constBegin();
5355 QStringList::ConstIterator fServiceNameIt
= frameServiceNames
.constBegin();
5356 KUrl::List::ConstIterator fURLIt
= frameURLs
.constBegin();
5357 QList
<QByteArray
>::ConstIterator fBufferIt
= frameStateBuffers
.constBegin();
5358 QList
<int>::ConstIterator fFrameTypeIt
= frameTypes
.constBegin();
5360 for (; fIt
!= fEnd
; ++fIt
, ++fNameIt
, ++fServiceTypeIt
, ++fServiceNameIt
, ++fURLIt
, ++fBufferIt
, ++fFrameTypeIt
)
5362 khtml::ChildFrame
* const child
= *fIt
;
5364 // kDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt;
5366 if ( child
->m_name
!= *fNameIt
|| child
->m_serviceType
!= *fServiceTypeIt
)
5368 child
->m_bPreloaded
= true;
5369 child
->m_name
= *fNameIt
;
5370 child
->m_serviceName
= *fServiceNameIt
;
5371 child
->m_type
= static_cast<khtml::ChildFrame::Type
>(*fFrameTypeIt
);
5372 processObjectRequest( child
, *fURLIt
, *fServiceTypeIt
);
5374 if ( child
->m_part
)
5376 child
->m_bCompleted
= false;
5377 if ( child
->m_extension
&& !(*fBufferIt
).isEmpty() )
5379 QDataStream
frameStream( *fBufferIt
);
5380 child
->m_extension
->restoreState( frameStream
);
5383 child
->m_part
->openUrl( *fURLIt
);
5387 KParts::OpenUrlArguments
args( arguments() );
5388 args
.setXOffset(xOffset
);
5389 args
.setYOffset(yOffset
);
5392 KParts::BrowserArguments
browserArgs( d
->m_extension
->browserArguments() );
5393 browserArgs
.docState
= docState
;
5394 d
->m_extension
->setBrowserArguments(browserArgs
);
5396 d
->m_view
->resizeContents( wContents
, hContents
);
5397 d
->m_view
->setContentsPos( xOffset
, yOffset
);
5405 // We must force a clear because we want to be sure to delete all
5407 d
->m_bCleared
= false;
5409 d
->m_encoding
= encoding
;
5410 d
->m_sheetUsed
= sheetUsed
;
5412 QStringList::ConstIterator fNameIt
= frameNames
.constBegin();
5413 const QStringList::ConstIterator fNameEnd
= frameNames
.constEnd();
5415 QStringList::ConstIterator fServiceTypeIt
= frameServiceTypes
.constBegin();
5416 QStringList::ConstIterator fServiceNameIt
= frameServiceNames
.constBegin();
5417 KUrl::List::ConstIterator fURLIt
= frameURLs
.constBegin();
5418 QList
<QByteArray
>::ConstIterator fBufferIt
= frameStateBuffers
.constBegin();
5419 QList
<int>::ConstIterator fFrameTypeIt
= frameTypes
.constBegin();
5421 for (; fNameIt
!= fNameEnd
; ++fNameIt
, ++fServiceTypeIt
, ++fServiceNameIt
, ++fURLIt
, ++fBufferIt
, ++fFrameTypeIt
)
5423 khtml::ChildFrame
* const newChild
= new khtml::ChildFrame
;
5424 newChild
->m_bPreloaded
= true;
5425 newChild
->m_name
= *fNameIt
;
5426 newChild
->m_serviceName
= *fServiceNameIt
;
5427 newChild
->m_type
= static_cast<khtml::ChildFrame::Type
>(*fFrameTypeIt
);
5429 // kDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt;
5431 const FrameIt childFrame
= d
->m_frames
.insert( d
->m_frames
.end(), newChild
);
5433 processObjectRequest( *childFrame
, *fURLIt
, *fServiceTypeIt
);
5435 (*childFrame
)->m_bPreloaded
= true;
5437 if ( (*childFrame
)->m_part
)
5439 if ( (*childFrame
)->m_extension
&& !(*fBufferIt
).isEmpty() )
5441 QDataStream
frameStream( *fBufferIt
);
5442 (*childFrame
)->m_extension
->restoreState( frameStream
);
5445 (*childFrame
)->m_part
->openUrl( *fURLIt
);
5449 KParts::OpenUrlArguments
args( arguments() );
5450 args
.setXOffset(xOffset
);
5451 args
.setYOffset(yOffset
);
5454 KParts::BrowserArguments
browserArgs( d
->m_extension
->browserArguments() );
5455 browserArgs
.docState
= docState
;
5456 d
->m_extension
->setBrowserArguments(browserArgs
);
5458 if (!KHTMLPageCache::self()->isComplete(d
->m_cacheId
))
5460 d
->m_restored
= true;
5462 d
->m_restored
= false;
5472 void KHTMLPart::show()
5478 void KHTMLPart::hide()
5484 DOM::Node
KHTMLPart::nodeUnderMouse() const
5486 return d
->m_view
->nodeUnderMouse();
5489 DOM::Node
KHTMLPart::nonSharedNodeUnderMouse() const
5491 return d
->m_view
->nonSharedNodeUnderMouse();
5494 void KHTMLPart::emitSelectionChanged()
5496 emit d
->m_extension
->enableAction( "copy", hasSelection() );
5498 emit d
->m_extension
->selectionInfo( selectedText() );
5499 emit
selectionChanged();
5502 int KHTMLPart::zoomFactor() const
5504 return d
->m_zoomFactor
;
5507 // ### make the list configurable ?
5508 static const int zoomSizes
[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
5509 static const int zoomSizeCount
= (sizeof(zoomSizes
) / sizeof(int));
5510 static const int minZoom
= 20;
5511 static const int maxZoom
= 300;
5513 // My idea of useful stepping ;-) (LS)
5514 extern const int KDE_NO_EXPORT fastZoomSizes
[] = { 20, 50, 75, 90, 100, 120, 150, 200, 300 };
5515 extern const int KDE_NO_EXPORT fastZoomSizeCount
= sizeof fastZoomSizes
/ sizeof fastZoomSizes
[0];
5517 void KHTMLPart::slotIncZoom()
5519 zoomIn(zoomSizes
, zoomSizeCount
);
5522 void KHTMLPart::slotDecZoom()
5524 zoomOut(zoomSizes
, zoomSizeCount
);
5527 void KHTMLPart::slotIncZoomFast()
5529 zoomIn(fastZoomSizes
, fastZoomSizeCount
);
5532 void KHTMLPart::slotDecZoomFast()
5534 zoomOut(fastZoomSizes
, fastZoomSizeCount
);
5537 void KHTMLPart::zoomIn(const int stepping
[], int count
)
5539 int zoomFactor
= d
->m_zoomFactor
;
5541 if (zoomFactor
< maxZoom
) {
5542 // find the entry nearest to the given zoomsizes
5543 for (int i
= 0; i
< count
; ++i
)
5544 if (stepping
[i
] > zoomFactor
) {
5545 zoomFactor
= stepping
[i
];
5548 setZoomFactor(zoomFactor
);
5552 void KHTMLPart::zoomOut(const int stepping
[], int count
)
5554 int zoomFactor
= d
->m_zoomFactor
;
5555 if (zoomFactor
> minZoom
) {
5556 // find the entry nearest to the given zoomsizes
5557 for (int i
= count
-1; i
>= 0; --i
)
5558 if (stepping
[i
] < zoomFactor
) {
5559 zoomFactor
= stepping
[i
];
5562 setZoomFactor(zoomFactor
);
5566 void KHTMLPart::setZoomFactor (int percent
)
5568 // ### zooming under 100% is majorly botched,
5569 // so disable that for now.
5570 if (percent
< 100) percent
= 100;
5571 // ### if (percent < minZoom) percent = minZoom;
5573 if (percent
> maxZoom
) percent
= maxZoom
;
5574 if (d
->m_zoomFactor
== percent
) return;
5575 d
->m_zoomFactor
= percent
;
5578 QApplication::setOverrideCursor( Qt::WaitCursor
);
5579 d
->m_view
->setZoomLevel( d
->m_zoomFactor
);
5580 QApplication::restoreOverrideCursor();
5583 ConstFrameIt it
= d
->m_frames
.constBegin();
5584 const ConstFrameIt end
= d
->m_frames
.constEnd();
5585 for (; it
!= end
; ++it
)
5586 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
5587 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
5588 static_cast<KHTMLPart
*>( p
)->setZoomFactor(d
->m_zoomFactor
);
5591 if ( d
->m_guiProfile
== BrowserViewGUI
) {
5592 d
->m_paDecZoomFactor
->setEnabled( d
->m_zoomFactor
> minZoom
);
5593 d
->m_paIncZoomFactor
->setEnabled( d
->m_zoomFactor
< maxZoom
);
5596 void KHTMLPart::slotIncFontSize()
5598 incFontSize(zoomSizes
, zoomSizeCount
);
5601 void KHTMLPart::slotDecFontSize()
5603 decFontSize(zoomSizes
, zoomSizeCount
);
5606 void KHTMLPart::slotIncFontSizeFast()
5608 incFontSize(fastZoomSizes
, fastZoomSizeCount
);
5611 void KHTMLPart::slotDecFontSizeFast()
5613 decFontSize(fastZoomSizes
, fastZoomSizeCount
);
5616 void KHTMLPart::incFontSize(const int stepping
[], int count
)
5618 int zoomFactor
= d
->m_fontScaleFactor
;
5620 if (zoomFactor
< maxZoom
) {
5621 // find the entry nearest to the given zoomsizes
5622 for (int i
= 0; i
< count
; ++i
)
5623 if (stepping
[i
] > zoomFactor
) {
5624 zoomFactor
= stepping
[i
];
5627 setFontScaleFactor(zoomFactor
);
5631 void KHTMLPart::decFontSize(const int stepping
[], int count
)
5633 int zoomFactor
= d
->m_fontScaleFactor
;
5634 if (zoomFactor
> minZoom
) {
5635 // find the entry nearest to the given zoomsizes
5636 for (int i
= count
-1; i
>= 0; --i
)
5637 if (stepping
[i
] < zoomFactor
) {
5638 zoomFactor
= stepping
[i
];
5641 setFontScaleFactor(zoomFactor
);
5645 void KHTMLPart::setFontScaleFactor(int percent
)
5647 if (percent
< minZoom
) percent
= minZoom
;
5648 if (percent
> maxZoom
) percent
= maxZoom
;
5649 if (d
->m_fontScaleFactor
== percent
) return;
5650 d
->m_fontScaleFactor
= percent
;
5652 if (d
->m_view
&& d
->m_doc
) {
5653 QApplication::setOverrideCursor( Qt::WaitCursor
);
5654 if (d
->m_doc
->styleSelector())
5655 d
->m_doc
->styleSelector()->computeFontSizes(d
->m_doc
->logicalDpiY(), d
->m_fontScaleFactor
);
5656 d
->m_doc
->recalcStyle( NodeImpl::Force
);
5657 QApplication::restoreOverrideCursor();
5660 ConstFrameIt it
= d
->m_frames
.constBegin();
5661 const ConstFrameIt end
= d
->m_frames
.constEnd();
5662 for (; it
!= end
; ++it
)
5663 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
5664 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
5665 static_cast<KHTMLPart
*>( p
)->setFontScaleFactor(d
->m_fontScaleFactor
);
5669 int KHTMLPart::fontScaleFactor() const
5671 return d
->m_fontScaleFactor
;
5674 void KHTMLPart::slotZoomView( int delta
)
5682 void KHTMLPart::setStatusBarText( const QString
& text
, StatusBarPriority p
)
5684 if (!d
->m_statusMessagesEnabled
)
5687 d
->m_statusBarText
[p
] = text
;
5690 QString tobe
= d
->m_statusBarText
[BarHoverText
];
5692 tobe
= d
->m_statusBarText
[BarOverrideText
];
5693 if (tobe
.isEmpty()) {
5694 tobe
= d
->m_statusBarText
[BarDefaultText
];
5695 if (!tobe
.isEmpty() && d
->m_jobspeed
)
5698 tobe
+= i18n( "(%1/s)" , KIO::convertSize( d
->m_jobspeed
) );
5702 emit
ReadOnlyPart::setStatusBarText(tobe
);
5706 void KHTMLPart::setJSStatusBarText( const QString
&text
)
5708 setStatusBarText(text
, BarOverrideText
);
5711 void KHTMLPart::setJSDefaultStatusBarText( const QString
&text
)
5713 setStatusBarText(text
, BarDefaultText
);
5716 QString
KHTMLPart::jsStatusBarText() const
5718 return d
->m_statusBarText
[BarOverrideText
];
5721 QString
KHTMLPart::jsDefaultStatusBarText() const
5723 return d
->m_statusBarText
[BarDefaultText
];
5726 QString
KHTMLPart::referrer() const
5728 return d
->m_referrer
;
5731 QString
KHTMLPart::pageReferrer() const
5733 KUrl referrerURL
= KUrl( d
->m_pageReferrer
);
5734 if (referrerURL
.isValid())
5736 QString protocol
= referrerURL
.protocol();
5738 if ((protocol
== "http") ||
5739 ((protocol
== "https") && (url().protocol() == "https")))
5741 referrerURL
.setRef(QString());
5742 referrerURL
.setUser(QString());
5743 referrerURL
.setPass(QString());
5744 return referrerURL
.url();
5752 QString
KHTMLPart::lastModified() const
5754 if ( d
->m_lastModified
.isEmpty() && url().isLocalFile() ) {
5755 // Local file: set last-modified from the file's mtime.
5756 // Done on demand to save time when this isn't needed - but can lead
5757 // to slightly wrong results if updating the file on disk w/o reloading.
5758 QDateTime lastModif
= QFileInfo( url().toLocalFile() ).lastModified();
5759 d
->m_lastModified
= lastModif
.toString( Qt::LocalDate
);
5761 //kDebug(6050) << d->m_lastModified;
5762 return d
->m_lastModified
;
5765 void KHTMLPart::slotLoadImages()
5768 d
->m_doc
->docLoader()->setAutoloadImages( !d
->m_doc
->docLoader()->autoloadImages() );
5770 ConstFrameIt it
= d
->m_frames
.constBegin();
5771 const ConstFrameIt end
= d
->m_frames
.constEnd();
5772 for (; it
!= end
; ++it
)
5773 if ( !( *it
)->m_part
.isNull() && (*it
)->m_part
->inherits( "KHTMLPart" ) ) {
5774 KParts::ReadOnlyPart
* const p
= ( *it
)->m_part
;
5775 static_cast<KHTMLPart
*>( p
)->slotLoadImages();
5779 void KHTMLPart::reparseConfiguration()
5781 KHTMLSettings
*settings
= KHTMLGlobal::defaultHTMLSettings();
5784 setAutoloadImages( settings
->autoLoadImages() );
5786 d
->m_doc
->docLoader()->setShowAnimations( settings
->showAnimations() );
5788 d
->m_bOpenMiddleClick
= settings
->isOpenMiddleClickEnabled();
5789 d
->m_bBackRightClick
= settings
->isBackRightClickEnabled();
5790 d
->m_bJScriptEnabled
= settings
->isJavaScriptEnabled(url().host());
5791 setDebugScript( settings
->isJavaScriptDebugEnabled() );
5792 d
->m_bJavaEnabled
= settings
->isJavaEnabled(url().host());
5793 d
->m_bPluginsEnabled
= settings
->isPluginsEnabled(url().host());
5794 d
->m_metaRefreshEnabled
= settings
->isAutoDelayedActionsEnabled ();
5796 delete d
->m_settings
;
5797 d
->m_settings
= new KHTMLSettings(*KHTMLGlobal::defaultHTMLSettings());
5799 QApplication::setOverrideCursor( Qt::WaitCursor
);
5800 khtml::CSSStyleSelector::reparseConfiguration();
5801 if(d
->m_doc
) d
->m_doc
->updateStyleSelector();
5802 QApplication::restoreOverrideCursor();
5805 KHTMLSettings::KSmoothScrollingMode ssm
= d
->m_settings
->smoothScrolling();
5806 if (ssm
== KHTMLSettings::KSmoothScrollingDisabled
)
5807 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMDisabled
);
5808 else if (ssm
== KHTMLSettings::KSmoothScrollingWhenEfficient
)
5809 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMWhenEfficient
);
5811 d
->m_view
->setSmoothScrollingModeDefault(KHTMLView::SSMEnabled
);
5814 if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled())
5818 QStringList
KHTMLPart::frameNames() const
5822 ConstFrameIt it
= d
->m_frames
.constBegin();
5823 const ConstFrameIt end
= d
->m_frames
.constEnd();
5824 for (; it
!= end
; ++it
)
5825 if (!(*it
)->m_bPreloaded
&& (*it
)->m_part
)
5826 res
+= (*it
)->m_name
;
5831 QList
<KParts::ReadOnlyPart
*> KHTMLPart::frames() const
5833 QList
<KParts::ReadOnlyPart
*> res
;
5835 ConstFrameIt it
= d
->m_frames
.constBegin();
5836 const ConstFrameIt end
= d
->m_frames
.constEnd();
5837 for (; it
!= end
; ++it
)
5838 if (!(*it
)->m_bPreloaded
&& (*it
)->m_part
) // ### TODO: make sure that we always create an empty
5839 // KHTMLPart for frames so this never happens.
5840 res
.append( (*it
)->m_part
);
5845 bool KHTMLPart::openUrlInFrame( const KUrl
&url
, const KParts::OpenUrlArguments
& args
, const KParts::BrowserArguments
&browserArgs
)
5847 kDebug( 6050 ) << this << url
;
5848 FrameIt it
= d
->m_frames
.find( browserArgs
.frameName
);
5850 if ( it
== d
->m_frames
.end() )
5853 // Inform someone that we are about to show something else.
5854 if ( !browserArgs
.lockHistory() )
5855 emit d
->m_extension
->openUrlNotify();
5857 requestObject( *it
, url
, args
, browserArgs
);
5862 void KHTMLPart::setDNDEnabled( bool b
)
5867 bool KHTMLPart::dndEnabled() const
5872 void KHTMLPart::customEvent( QEvent
*event
)
5874 if ( khtml::MousePressEvent::test( event
) )
5876 khtmlMousePressEvent( static_cast<khtml::MousePressEvent
*>( event
) );
5880 if ( khtml::MouseDoubleClickEvent::test( event
) )
5882 khtmlMouseDoubleClickEvent( static_cast<khtml::MouseDoubleClickEvent
*>( event
) );
5886 if ( khtml::MouseMoveEvent::test( event
) )
5888 khtmlMouseMoveEvent( static_cast<khtml::MouseMoveEvent
*>( event
) );
5892 if ( khtml::MouseReleaseEvent::test( event
) )
5894 khtmlMouseReleaseEvent( static_cast<khtml::MouseReleaseEvent
*>( event
) );
5898 if ( khtml::DrawContentsEvent::test( event
) )
5900 khtmlDrawContentsEvent( static_cast<khtml::DrawContentsEvent
*>( event
) );
5904 KParts::ReadOnlyPart::customEvent( event
);
5907 bool KHTMLPart::isPointInsideSelection(int x
, int y
)
5909 // Treat a collapsed selection like no selection.
5910 if (d
->editor_context
.m_selection
.state() == Selection::CARET
)
5912 if (!xmlDocImpl()->renderer())
5915 khtml::RenderObject::NodeInfo
nodeInfo(true, true);
5916 xmlDocImpl()->renderer()->layer()->nodeAtPoint(nodeInfo
, x
, y
);
5917 NodeImpl
*innerNode
= nodeInfo
.innerNode();
5918 if (!innerNode
|| !innerNode
->renderer())
5921 return innerNode
->isPointInsideSelection(x
, y
, d
->editor_context
.m_selection
);
5924 /** returns the position of the first inline text box of the line at
5925 * coordinate y in renderNode
5927 * This is a helper function for line-by-line text selection.
5929 static bool firstRunAt(khtml::RenderObject
*renderNode
, int y
, NodeImpl
*&startNode
, long &startOffset
)
5931 for (khtml::RenderObject
*n
= renderNode
; n
; n
= n
->nextSibling()) {
5933 khtml::RenderText
* const textRenderer
= static_cast<khtml::RenderText
*>(n
);
5934 for (khtml::InlineTextBox
* box
= textRenderer
->firstTextBox(); box
; box
= box
->nextTextBox()) {
5935 if (box
->m_y
== y
&& textRenderer
->element()) {
5936 startNode
= textRenderer
->element();
5937 startOffset
= box
->m_start
;
5943 if (firstRunAt(n
->firstChild(), y
, startNode
, startOffset
)) {
5951 /** returns the position of the last inline text box of the line at
5952 * coordinate y in renderNode
5954 * This is a helper function for line-by-line text selection.
5956 static bool lastRunAt(khtml::RenderObject
*renderNode
, int y
, NodeImpl
*&endNode
, long &endOffset
)
5958 khtml::RenderObject
*n
= renderNode
;
5962 khtml::RenderObject
*next
;
5963 while ((next
= n
->nextSibling())) {
5968 if (lastRunAt(n
->firstChild(), y
, endNode
, endOffset
)) {
5973 khtml::RenderText
* const textRenderer
= static_cast<khtml::RenderText
*>(n
);
5974 for (khtml::InlineTextBox
* box
= textRenderer
->firstTextBox(); box
; box
= box
->nextTextBox()) {
5975 if (box
->m_y
== y
&& textRenderer
->element()) {
5976 endNode
= textRenderer
->element();
5977 endOffset
= box
->m_start
+ box
->m_len
;
5983 if (n
== renderNode
) {
5987 n
= n
->previousSibling();
5991 void KHTMLPart::handleMousePressEventDoubleClick(khtml::MouseDoubleClickEvent
*event
)
5993 QMouseEvent
*mouse
= event
->qmouseEvent();
5994 DOM::Node innerNode
= event
->innerNode();
5996 Selection selection
;
5998 if (mouse
->button() == Qt::LeftButton
&& !innerNode
.isNull() && innerNode
.handle()->renderer() &&
5999 innerNode
.handle()->renderer()->shouldSelect()) {
6000 Position
pos(innerNode
.handle()->positionForCoordinates(event
->x(), event
->y()));
6001 if (pos
.node() && (pos
.node()->nodeType() == Node::TEXT_NODE
|| pos
.node()->nodeType() == Node::CDATA_SECTION_NODE
)) {
6002 selection
.moveTo(pos
);
6003 selection
.expandUsingGranularity(Selection::WORD
);
6007 if (selection
.state() != Selection::CARET
) {
6008 d
->editor_context
.beginSelectingText(Selection::WORD
);
6011 setCaret(selection
);
6015 void KHTMLPart::handleMousePressEventTripleClick(khtml::MouseDoubleClickEvent
*event
)
6017 QMouseEvent
*mouse
= event
->qmouseEvent();
6018 DOM::Node innerNode
= event
->innerNode();
6020 Selection selection
;
6022 if (mouse
->button() == Qt::LeftButton
&& !innerNode
.isNull() && innerNode
.handle()->renderer() &&
6023 innerNode
.handle()->renderer()->shouldSelect()) {
6024 Position
pos(innerNode
.handle()->positionForCoordinates(event
->x(), event
->y()));
6025 if (pos
.node() && (pos
.node()->nodeType() == Node::TEXT_NODE
|| pos
.node()->nodeType() == Node::CDATA_SECTION_NODE
)) {
6026 selection
.moveTo(pos
);
6027 selection
.expandUsingGranularity(Selection::LINE
);
6031 if (selection
.state() != Selection::CARET
) {
6032 d
->editor_context
.beginSelectingText(Selection::LINE
);
6035 setCaret(selection
);
6039 void KHTMLPart::handleMousePressEventSingleClick(khtml::MousePressEvent
*event
)
6041 QMouseEvent
*mouse
= event
->qmouseEvent();
6042 DOM::Node innerNode
= event
->innerNode();
6044 if (mouse
->button() == Qt::LeftButton
) {
6047 if (!innerNode
.isNull() && innerNode
.handle()->renderer() &&
6048 innerNode
.handle()->renderer()->shouldSelect()) {
6049 bool extendSelection
= mouse
->modifiers() & Qt::ShiftModifier
;
6051 // Don't restart the selection when the mouse is pressed on an
6052 // existing selection so we can allow for text dragging.
6053 if (!extendSelection
&& isPointInsideSelection(event
->x(), event
->y())) {
6056 Position
pos(innerNode
.handle()->positionForCoordinates(event
->x(), event
->y()));
6058 pos
= Position(innerNode
.handle(), innerNode
.handle()->caretMinOffset());
6061 if (extendSelection
&& sel
.notEmpty()) {
6062 sel
.clearModifyBias();
6064 if (d
->editor_context
.m_selectionGranularity
!= Selection::CHARACTER
) {
6065 sel
.expandUsingGranularity(d
->editor_context
.m_selectionGranularity
);
6067 d
->editor_context
.m_beganSelectingText
= true;
6070 d
->editor_context
.m_selectionGranularity
= Selection::CHARACTER
;
6079 void KHTMLPart::khtmlMousePressEvent( khtml::MousePressEvent
*event
)
6081 DOM::DOMString url
= event
->url();
6082 QMouseEvent
*_mouse
= event
->qmouseEvent();
6083 DOM::Node innerNode
= event
->innerNode();
6084 d
->m_mousePressNode
= innerNode
;
6086 d
->m_dragStartPos
= QPoint(event
->x(), event
->y());
6088 if ( !event
->url().isNull() ) {
6089 d
->m_strSelectedURL
= event
->url().string();
6090 d
->m_strSelectedURLTarget
= event
->target().string();
6093 d
->m_strSelectedURL
.clear();
6094 d
->m_strSelectedURLTarget
.clear();
6097 if ( _mouse
->button() == Qt::LeftButton
||
6098 _mouse
->button() == Qt::MidButton
)
6100 d
->m_bMousePressed
= true;
6102 #ifdef KHTML_NO_SELECTION
6103 d
->m_dragLastPos
= _mouse
->globalPos();
6105 if ( _mouse
->button() == Qt::LeftButton
)
6107 if ( (!d
->m_strSelectedURL
.isNull() && !isEditable())
6108 || (!d
->m_mousePressNode
.isNull() && d
->m_mousePressNode
.elementId() == ID_IMG
) )
6111 d
->editor_context
.m_beganSelectingText
= false;
6113 handleMousePressEventSingleClick(event
);
6118 if ( _mouse
->button() == Qt::RightButton
&& parentPart() != 0 && d
->m_bBackRightClick
)
6120 d
->m_bRightMousePressed
= true;
6121 } else if ( _mouse
->button() == Qt::RightButton
)
6123 popupMenu( d
->m_strSelectedURL
);
6124 // might be deleted, don't touch "this"
6128 void KHTMLPart::khtmlMouseDoubleClickEvent( khtml::MouseDoubleClickEvent
*event
)
6130 QMouseEvent
*_mouse
= event
->qmouseEvent();
6131 if ( _mouse
->button() == Qt::LeftButton
)
6133 d
->m_bMousePressed
= true;
6134 d
->editor_context
.m_beganSelectingText
= false;
6136 if (event
->clickCount() == 2) {
6137 handleMousePressEventDoubleClick(event
);
6141 if (event
->clickCount() >= 3) {
6142 handleMousePressEventTripleClick(event
);
6148 #ifndef KHTML_NO_SELECTION
6149 bool KHTMLPart::isExtendingSelection() const
6151 // This is it, the whole detection. khtmlMousePressEvent only sets this
6152 // on LMB or MMB, but never on RMB. As text selection doesn't work for MMB,
6153 // it's sufficient to only rely on this flag to detect selection extension.
6154 return d
->editor_context
.m_beganSelectingText
;
6157 void KHTMLPart::extendSelectionTo(int x
, int y
, const DOM::Node
&innerNode
)
6159 // handle making selection
6160 Position
pos(innerNode
.handle()->positionForCoordinates(x
, y
));
6162 // Don't modify the selection if we're not on a node.
6166 // Restart the selection if this is the first mouse move. This work is usually
6167 // done in khtmlMousePressEvent, but not if the mouse press was on an existing selection.
6168 Selection sel
= caret();
6169 sel
.clearModifyBias();
6170 if (!d
->editor_context
.m_beganSelectingText
) {
6171 // We are beginning a selection during press-drag, when the original click
6172 // wasn't appropriate for one. Make sure to set the granularity.
6173 d
->editor_context
.beginSelectingText(Selection::CHARACTER
);
6178 if (d
->editor_context
.m_selectionGranularity
!= Selection::CHARACTER
) {
6179 sel
.expandUsingGranularity(d
->editor_context
.m_selectionGranularity
);
6184 #endif // KHTML_NO_SELECTION
6186 bool KHTMLPart::handleMouseMoveEventDrag(khtml::MouseMoveEvent
*event
)
6188 #ifdef QT_NO_DRAGANDDROP
6191 DOM::Node innerNode
= event
->innerNode();
6193 if( (d
->m_bMousePressed
&&
6194 ( (!d
->m_strSelectedURL
.isEmpty() && !isEditable())
6195 || (!d
->m_mousePressNode
.isNull() && d
->m_mousePressNode
.elementId() == ID_IMG
) ) )
6196 && ( d
->m_dragStartPos
- QPoint(event
->x(), event
->y()) ).manhattanLength() > KGlobalSettings::dndEventDelay() ) {
6198 DOM::DOMString url
= event
->url();
6201 HTMLImageElementImpl
*img
= 0L;
6204 // qDebug("****************** Event URL: %s", url.string().toLatin1().constData());
6205 // qDebug("****************** Event Target: %s", target.string().toLatin1().constData());
6208 if ( url
.length() == 0 && innerNode
.handle() && innerNode
.handle()->id() == ID_IMG
)
6210 img
= static_cast<HTMLImageElementImpl
*>(innerNode
.handle());
6211 u
= KUrl( completeURL( khtml::parseURL(img
->getAttribute(ATTR_SRC
)).string() ) );
6212 pix
= KIconLoader::global()->loadIcon("image-x-generic", KIconLoader::Desktop
);
6216 // Text or image link...
6217 u
= completeURL( d
->m_strSelectedURL
);
6218 pix
= KIO::pixmapForUrl(u
, 0, KIconLoader::Desktop
, KIconLoader::SizeMedium
);
6221 u
.setPass(QString());
6223 QDrag
*drag
= new QDrag( d
->m_view
->viewport() );
6224 QMap
<QString
, QString
> metaDataMap
;
6225 if ( !d
->m_referrer
.isEmpty() )
6226 metaDataMap
.insert( "referrer", d
->m_referrer
);
6227 QMimeData
* mimeData
= new QMimeData();
6228 u
.populateMimeData( mimeData
, metaDataMap
);
6229 drag
->setMimeData( mimeData
);
6231 if( img
&& img
->complete() )
6232 drag
->mimeData()->setImageData( img
->currentImage() );
6234 if ( !pix
.isNull() )
6235 drag
->setPixmap( pix
);
6240 // when we finish our drag, we need to undo our mouse press
6241 d
->m_bMousePressed
= false;
6242 d
->m_strSelectedURL
.clear();
6243 d
->m_strSelectedURLTarget
.clear();
6247 #endif // QT_NO_DRAGANDDROP
6250 bool KHTMLPart::handleMouseMoveEventOver(khtml::MouseMoveEvent
*event
)
6252 // Mouse clicked -> do nothing
6253 if ( d
->m_bMousePressed
) return false;
6255 DOM::DOMString url
= event
->url();
6257 // The mouse is over something
6260 DOM::DOMString target
= event
->target();
6261 QMouseEvent
*_mouse
= event
->qmouseEvent();
6262 DOM::Node innerNode
= event
->innerNode();
6264 bool shiftPressed
= ( _mouse
->modifiers() & Qt::ShiftModifier
);
6267 if ( !innerNode
.isNull() && innerNode
.elementId() == ID_IMG
)
6269 HTMLImageElementImpl
*i
= static_cast<HTMLImageElementImpl
*>(innerNode
.handle());
6270 if ( i
&& i
->isServerMap() )
6272 khtml::RenderObject
*r
= i
->renderer();
6276 r
->absolutePosition(absx
, absy
);
6277 int x(event
->x() - absx
), y(event
->y() - absy
);
6279 d
->m_overURL
= url
.string() + QString("?%1,%2").arg(x
).arg(y
);
6280 d
->m_overURLTarget
= target
.string();
6281 overURL( d
->m_overURL
, target
.string(), shiftPressed
);
6288 if ( d
->m_overURL
.isEmpty() || d
->m_overURL
!= url
|| d
->m_overURLTarget
!= target
)
6290 d
->m_overURL
= url
.string();
6291 d
->m_overURLTarget
= target
.string();
6292 overURL( d
->m_overURL
, target
.string(), shiftPressed
);
6295 else // Not over a link...
6297 if( !d
->m_overURL
.isEmpty() ) // and we were over a link -> reset to "default statusbar text"
6299 // reset to "default statusbar text"
6306 void KHTMLPart::handleMouseMoveEventSelection(khtml::MouseMoveEvent
*event
)
6308 // Mouse not pressed. Do nothing.
6309 if (!d
->m_bMousePressed
)
6312 #ifdef KHTML_NO_SELECTION
6313 if (d
->m_doc
&& d
->m_view
) {
6314 QPoint
diff( mouse
->globalPos() - d
->m_dragLastPos
);
6316 if (abs(diff
.x()) > 64 || abs(diff
.y()) > 64) {
6317 d
->m_view
->scrollBy(-diff
.x(), -diff
.y());
6318 d
->m_dragLastPos
= mouse
->globalPos();
6323 QMouseEvent
*mouse
= event
->qmouseEvent();
6324 DOM::Node innerNode
= event
->innerNode();
6326 if ( (mouse
->buttons() & Qt::LeftButton
) == 0 || !innerNode
.handle() || !innerNode
.handle()->renderer() ||
6327 !innerNode
.handle()->renderer()->shouldSelect())
6330 // handle making selection
6331 extendSelectionTo(event
->x(), event
->y(), innerNode
);
6332 #endif // KHTML_NO_SELECTION
6335 void KHTMLPart::khtmlMouseMoveEvent( khtml::MouseMoveEvent
*event
)
6337 if (handleMouseMoveEventDrag(event
))
6340 if (handleMouseMoveEventOver(event
))
6343 handleMouseMoveEventSelection(event
);
6346 void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent
*event
)
6348 DOM::Node innerNode
= event
->innerNode();
6349 d
->m_mousePressNode
= DOM::Node();
6351 if ( d
->m_bMousePressed
) {
6352 setStatusBarText(QString(), BarHoverText
);
6356 // Used to prevent mouseMoveEvent from initiating a drag before
6357 // the mouse is pressed again.
6358 d
->m_bMousePressed
= false;
6360 QMouseEvent
*_mouse
= event
->qmouseEvent();
6361 if ( _mouse
->button() == Qt::RightButton
&& parentPart() != 0 && d
->m_bBackRightClick
)
6363 d
->m_bRightMousePressed
= false;
6364 KParts::BrowserInterface
*tmp_iface
= d
->m_extension
->browserInterface();
6366 tmp_iface
->callMethod( "goHistory", -1 );
6369 #ifndef QT_NO_CLIPBOARD
6370 if ((d
->m_guiProfile
== BrowserViewGUI
) && (_mouse
->button() == Qt::MidButton
) && (event
->url().isNull())) {
6371 kDebug( 6050 ) << "MMB shouldOpen=" << d
->m_bOpenMiddleClick
;
6373 if (d
->m_bOpenMiddleClick
) {
6374 KHTMLPart
*p
= this;
6375 while (p
->parentPart()) p
= p
->parentPart();
6376 p
->d
->m_extension
->pasteRequest();
6381 #ifndef KHTML_NO_SELECTION
6384 // Clear the selection if the mouse didn't move after the last mouse press.
6385 // We do this so when clicking on the selection, the selection goes away.
6386 // However, if we are editing, place the caret.
6387 if (!d
->editor_context
.m_beganSelectingText
6388 && d
->m_dragStartPos
.x() == event
->x()
6389 && d
->m_dragStartPos
.y() == event
->y()
6390 && d
->editor_context
.m_selection
.state() == Selection::RANGE
) {
6391 Selection selection
;
6392 #ifdef APPLE_CHANGES
6393 if (d
->editor_context
.m_selection
.base().node()->isContentEditable())
6395 selection
.moveTo(d
->editor_context
.m_selection
.base().node()->positionForCoordinates(event
->x(), event
->y()));
6396 setCaret(selection
);
6398 // get selected text and paste to the clipboard
6399 #ifndef QT_NO_CLIPBOARD
6400 QString text
= selectedText();
6401 text
.replace(QChar(0xa0), ' ');
6402 if (!text
.isEmpty()) {
6403 disconnect( qApp
->clipboard(), SIGNAL( selectionChanged()), this, SLOT( slotClearSelection()));
6404 qApp
->clipboard()->setText(text
,QClipboard::Selection
);
6405 connect( qApp
->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
6408 //kDebug( 6000 ) << "selectedText = " << text;
6409 emitSelectionChanged();
6410 //kDebug(6000) << "rel2: startBefEnd " << d->m_startBeforeEnd << " extAtEnd " << d->m_extendAtEnd << " (" << d->m_startOffset << ") - (" << d->m_endOffset << "), caretOfs " << d->caretOffset();
6415 void KHTMLPart::khtmlDrawContentsEvent( khtml::DrawContentsEvent
* )
6419 void KHTMLPart::guiActivateEvent( KParts::GUIActivateEvent
*event
)
6421 if ( event
->activated() )
6423 emitSelectionChanged();
6424 emit d
->m_extension
->enableAction( "print", d
->m_doc
!= 0 );
6426 if ( !d
->m_settings
->autoLoadImages() && d
->m_paLoadImages
)
6428 QList
<QAction
*> lst
;
6429 lst
.append( d
->m_paLoadImages
);
6430 plugActionList( "loadImages", lst
);
6435 void KHTMLPart::slotPrintFrame()
6437 if ( d
->m_frames
.count() == 0 )
6440 KParts::ReadOnlyPart
*frame
= currentFrame();
6444 KParts::BrowserExtension
*ext
= KParts::BrowserExtension::childObject( frame
);
6450 const QMetaObject
*mo
= ext
->metaObject();
6453 if (mo
->indexOfSlot( "print()") != -1)
6454 QMetaObject::invokeMethod(ext
, "print()", Qt::DirectConnection
);
6457 void KHTMLPart::slotSelectAll()
6459 KParts::ReadOnlyPart
*part
= currentFrame();
6460 if (part
&& part
->inherits("KHTMLPart"))
6461 static_cast<KHTMLPart
*>(part
)->selectAll();
6464 void KHTMLPart::startAutoScroll()
6466 connect(&d
->m_scrollTimer
, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
6467 d
->m_scrollTimer
.setSingleShot(false);
6468 d
->m_scrollTimer
.start(100);
6471 void KHTMLPart::stopAutoScroll()
6473 disconnect(&d
->m_scrollTimer
, SIGNAL( timeout() ), this, SLOT( slotAutoScroll() ));
6474 if (d
->m_scrollTimer
.isActive())
6475 d
->m_scrollTimer
.stop();
6479 void KHTMLPart::slotAutoScroll()
6482 d
->m_view
->doAutoScroll();
6484 stopAutoScroll(); // Safety
6487 void KHTMLPart::runAdFilter()
6490 parentPart()->runAdFilter();
6495 QSetIterator
<khtml::CachedObject
*> it( d
->m_doc
->docLoader()->m_docObjects
);
6496 while (it
.hasNext())
6498 khtml::CachedObject
* obj
= it
.next();
6499 if ( obj
->type() == khtml::CachedObject::Image
) {
6500 khtml::CachedImage
*image
= static_cast<khtml::CachedImage
*>(obj
);
6501 bool wasBlocked
= image
->m_wasBlocked
;
6502 image
->m_wasBlocked
= KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d
->m_doc
->completeURL( image
->url().string() ) );
6503 if ( image
->m_wasBlocked
!= wasBlocked
)
6504 image
->do_notify(QRect(QPoint(0,0), image
->pixmap_size()));
6508 if ( KHTMLGlobal::defaultHTMLSettings()->isHideAdsEnabled() ) {
6509 for ( NodeImpl
*nextNode
, *node
= d
->m_doc
; node
; node
= nextNode
) {
6511 // We might be deleting 'node' shortly.
6512 nextNode
= node
->traverseNextNode();
6514 if ( node
->id() == ID_IMG
||
6515 node
->id() == ID_IFRAME
||
6516 (node
->id() == ID_INPUT
&& static_cast<HTMLInputElementImpl
*>(node
)->inputType() == HTMLInputElementImpl::IMAGE
))
6518 if ( KHTMLGlobal::defaultHTMLSettings()->isAdFiltered( d
->m_doc
->completeURL( static_cast<ElementImpl
*>(node
)->getAttribute(ATTR_SRC
).string() ) ) )
6520 // We found an IMG, IFRAME or INPUT (of type IMAGE) matching a filter.
6522 NodeImpl
*parent
= node
->parent();
6526 parent
->removeChild(node
, exception
);
6535 void KHTMLPart::selectAll()
6537 if (!d
->m_doc
) return;
6540 if (d
->m_doc
->isHTMLDocument())
6541 first
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body();
6546 // Look for first text/cdata node that has a renderer,
6547 // or first childless replaced element
6548 while ( first
&& !(first
->renderer()
6549 && ((first
->nodeType() == Node::TEXT_NODE
|| first
->nodeType() == Node::CDATA_SECTION_NODE
)
6550 || (first
->renderer()->isReplaced() && !first
->renderer()->firstChild()))))
6552 next
= first
->firstChild();
6553 if ( !next
) next
= first
->nextSibling();
6554 while( first
&& !next
)
6556 first
= first
->parentNode();
6558 next
= first
->nextSibling();
6564 if (d
->m_doc
->isHTMLDocument())
6565 last
= static_cast<HTMLDocumentImpl
*>(d
->m_doc
)->body();
6568 // Look for last text/cdata node that has a renderer,
6569 // or last childless replaced element
6570 // ### Instead of changing this loop, use findLastSelectableNode
6571 // in render_table.cpp (LS)
6572 while ( last
&& !(last
->renderer()
6573 && ((last
->nodeType() == Node::TEXT_NODE
|| last
->nodeType() == Node::CDATA_SECTION_NODE
)
6574 || (last
->renderer()->isReplaced() && !last
->renderer()->lastChild()))))
6576 next
= last
->lastChild();
6577 if ( !next
) next
= last
->previousSibling();
6578 while ( last
&& !next
)
6580 last
= last
->parentNode();
6582 next
= last
->previousSibling();
6587 if ( !first
|| !last
)
6589 Q_ASSERT(first
->renderer());
6590 Q_ASSERT(last
->renderer());
6591 d
->editor_context
.m_selection
.moveTo(Position(first
, 0), Position(last
, last
->nodeValue().length()));
6592 d
->m_doc
->updateSelection();
6594 emitSelectionChanged();
6597 bool KHTMLPart::checkLinkSecurity(const KUrl
&linkURL
,const KLocalizedString
&message
, const QString
&button
)
6599 bool linkAllowed
= true;
6602 linkAllowed
= KAuthorized::authorizeUrlAction("redirect", url(), linkURL
);
6604 if ( !linkAllowed
) {
6605 khtml::Tokenizer
*tokenizer
= d
->m_doc
->tokenizer();
6607 tokenizer
->setOnHold(true);
6609 int response
= KMessageBox::Cancel
;
6610 if (!message
.isEmpty())
6612 // Dangerous flag makes the Cancel button the default
6613 response
= KMessageBox::warningContinueCancel( 0,
6614 message
.subs(Qt::escape(linkURL
.prettyUrl())).toString(),
6615 i18n( "Security Warning" ),
6617 KStandardGuiItem::cancel(),
6618 QString(), // no don't ask again info
6619 KMessageBox::Notify
| KMessageBox::Dangerous
);
6623 KMessageBox::error( 0,
6624 i18n( "<qt>Access by untrusted page to<br /><b>%1</b><br /> denied.</qt>", Qt::escape(linkURL
.prettyUrl())),
6625 i18n( "Security Alert" ));
6629 tokenizer
->setOnHold(false);
6630 return (response
==KMessageBox::Continue
);
6635 void KHTMLPart::slotPartRemoved( KParts::Part
*part
)
6637 // kDebug(6050) << part;
6638 if ( part
== d
->m_activeFrame
)
6640 d
->m_activeFrame
= 0L;
6641 if ( !part
->inherits( "KHTMLPart" ) )
6644 factory()->removeClient( part
);
6646 if (childClients().contains(part
)) {
6647 removeChildClient( part
);
6653 void KHTMLPart::slotActiveFrameChanged( KParts::Part
*part
)
6655 // kDebug(6050) << this << "part=" << part;
6658 kError(6050) << "strange error! we activated ourselves";
6662 // kDebug(6050) << "d->m_activeFrame=" << d->m_activeFrame;
6663 if ( d
->m_activeFrame
&& d
->m_activeFrame
->widget() && d
->m_activeFrame
->widget()->inherits( "QFrame" ) )
6665 QFrame
*frame
= static_cast<QFrame
*>( d
->m_activeFrame
->widget() );
6666 if (frame
->frameStyle() != QFrame::NoFrame
)
6668 frame
->setFrameStyle( QFrame::StyledPanel
| QFrame::Sunken
);
6673 if( d
->m_activeFrame
&& !d
->m_activeFrame
->inherits( "KHTMLPart" ) )
6676 factory()->removeClient( d
->m_activeFrame
);
6678 removeChildClient( d
->m_activeFrame
);
6680 if( part
&& !part
->inherits( "KHTMLPart" ) )
6683 factory()->addClient( part
);
6685 insertChildClient( part
);
6689 d
->m_activeFrame
= part
;
6691 if ( d
->m_activeFrame
&& d
->m_activeFrame
->widget()->inherits( "QFrame" ) )
6693 QFrame
*frame
= static_cast<QFrame
*>( d
->m_activeFrame
->widget() );
6694 if (frame
->frameStyle() != QFrame::NoFrame
)
6696 frame
->setFrameStyle( QFrame::StyledPanel
| QFrame::Plain
);
6699 kDebug(6050) << "new active frame " << d
->m_activeFrame
;
6704 // (note: childObject returns 0 if the argument is 0)
6705 d
->m_extension
->setExtensionProxy( KParts::BrowserExtension::childObject( d
->m_activeFrame
) );
6708 void KHTMLPart::setActiveNode(const DOM::Node
&node
)
6710 if (!d
->m_doc
|| !d
->m_view
)
6713 // Set the document's active node
6714 d
->m_doc
->setFocusNode(node
.handle());
6716 // Scroll the view if necessary to ensure that the new focus node is visible
6717 QRect rect
= node
.handle()->getRect();
6718 d
->m_view
->ensureVisible(rect
.right(), rect
.bottom());
6719 d
->m_view
->ensureVisible(rect
.left(), rect
.top());
6722 DOM::Node
KHTMLPart::activeNode() const
6724 return DOM::Node(d
->m_doc
?d
->m_doc
->focusNode():0);
6727 DOM::EventListener
*KHTMLPart::createHTMLEventListener( QString code
, QString name
, NodeImpl
* node
, bool svg
)
6729 KJSProxy
*proxy
= jScript();
6734 return proxy
->createHTMLEventHandler( url().url(), name
, code
, node
, svg
);
6737 KHTMLPart
*KHTMLPart::opener()
6742 void KHTMLPart::setOpener(KHTMLPart
*_opener
)
6744 d
->m_opener
= _opener
;
6747 bool KHTMLPart::openedByJS()
6749 return d
->m_openedByJS
;
6752 void KHTMLPart::setOpenedByJS(bool _openedByJS
)
6754 d
->m_openedByJS
= _openedByJS
;
6757 void KHTMLPart::preloadStyleSheet(const QString
&url
, const QString
&stylesheet
)
6759 khtml::Cache::preloadStyleSheet(url
, stylesheet
);
6762 void KHTMLPart::preloadScript(const QString
&url
, const QString
&script
)
6764 khtml::Cache::preloadScript(url
, script
);
6767 long KHTMLPart::cacheId() const
6769 return d
->m_cacheId
;
6772 bool KHTMLPart::restored() const
6774 return d
->m_restored
;
6777 bool KHTMLPart::pluginPageQuestionAsked(const QString
& mimetype
) const
6779 // parentPart() should be const!
6780 KHTMLPart
* parent
= const_cast<KHTMLPart
*>(this)->parentPart();
6782 return parent
->pluginPageQuestionAsked(mimetype
);
6784 return d
->m_pluginPageQuestionAsked
.contains(mimetype
);
6787 void KHTMLPart::setPluginPageQuestionAsked(const QString
& mimetype
)
6790 parentPart()->setPluginPageQuestionAsked(mimetype
);
6792 d
->m_pluginPageQuestionAsked
.append(mimetype
);
6795 KEncodingDetector
*KHTMLPart::createDecoder()
6797 KEncodingDetector
*dec
= new KEncodingDetector();
6798 if( !d
->m_encoding
.isNull() )
6799 dec
->setEncoding( d
->m_encoding
.toLatin1().constData(),
6800 d
->m_haveEncoding
? KEncodingDetector::UserChosenEncoding
: KEncodingDetector::EncodingFromHTTPHeader
);
6802 // Inherit the default encoding from the parent frame if there is one.
6803 QByteArray defaultEncoding
= (parentPart() && parentPart()->d
->m_decoder
)
6804 ? QByteArray( parentPart()->d
->m_decoder
->encoding() ) : settings()->encoding().toLatin1();
6805 dec
->setEncoding(defaultEncoding
.constData(), KEncodingDetector::DefaultEncoding
);
6807 #ifdef APPLE_CHANGES
6809 d
->m_doc
->setDecoder(d
->m_decoder
);
6811 dec
->setAutoDetectLanguage( d
->m_autoDetectLanguage
);
6815 void KHTMLPart::emitCaretPositionChanged(const DOM::Position
&pos
) {
6816 // pos must not be already converted to range-compliant coordinates
6817 Position rng_pos
= pos
.equivalentRangeCompliantPosition();
6818 Node node
= rng_pos
.node();
6819 emit
caretPositionChanged(node
, rng_pos
.offset());
6822 void KHTMLPart::restoreScrollPosition()
6824 const KParts::OpenUrlArguments
args( arguments() );
6826 if ( url().hasRef() && !d
->m_restoreScrollPosition
&& !args
.reload()) {
6827 if ( !d
->m_doc
|| !d
->m_doc
->parsing() )
6828 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
6829 if ( !gotoAnchor(url().encodedHtmlRef()) )
6830 gotoAnchor(url().htmlRef());
6834 // Check whether the viewport has become large enough to encompass the stored
6835 // offsets. If the document has been fully loaded, force the new coordinates,
6836 // even if the canvas is too short (can happen when user resizes the window
6838 if (d
->m_view
->contentsHeight() - d
->m_view
->visibleHeight() >= args
.yOffset()
6839 || d
->m_bComplete
) {
6840 d
->m_view
->setContentsPos(args
.xOffset(), args
.yOffset());
6841 disconnect(d
->m_view
, SIGNAL(finishedLayout()), this, SLOT(restoreScrollPosition()));
6846 void KHTMLPart::openWallet(DOM::HTMLFormElementImpl
*form
)
6848 #ifndef KHTML_NO_WALLET
6851 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart()) {
6855 p
->openWallet(form
);
6859 if (onlyLocalReferences()) { // avoid triggering on local apps, thumbnails
6864 if (d
->m_bWalletOpened
) {
6865 if (d
->m_wallet
->isOpen()) {
6866 form
->walletOpened(d
->m_wallet
);
6869 d
->m_wallet
->deleteLater();
6871 d
->m_bWalletOpened
= false;
6876 KWallet::Wallet
*wallet
= KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous
);
6877 d
->m_wq
= new KHTMLWalletQueue(this);
6878 d
->m_wq
->wallet
= wallet
;
6879 connect(wallet
, SIGNAL(walletOpened(bool)), d
->m_wq
, SLOT(walletOpened(bool)));
6880 connect(d
->m_wq
, SIGNAL(walletOpened(KWallet::Wallet
*)), this, SLOT(walletOpened(KWallet::Wallet
*)));
6883 d
->m_wq
->callers
.append(KHTMLWalletQueue::Caller(form
, form
->document()));
6884 #endif // KHTML_NO_WALLET
6888 void KHTMLPart::saveToWallet(const QString
& key
, const QMap
<QString
,QString
>& data
)
6890 #ifndef KHTML_NO_WALLET
6893 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart()) {
6897 p
->saveToWallet(key
, data
);
6902 if (d
->m_bWalletOpened
) {
6903 if (d
->m_wallet
->isOpen()) {
6904 if (!d
->m_wallet
->hasFolder(KWallet::Wallet::FormDataFolder())) {
6905 d
->m_wallet
->createFolder(KWallet::Wallet::FormDataFolder());
6907 d
->m_wallet
->setFolder(KWallet::Wallet::FormDataFolder());
6908 d
->m_wallet
->writeMap(key
, data
);
6911 d
->m_wallet
->deleteLater();
6913 d
->m_bWalletOpened
= false;
6918 KWallet::Wallet
*wallet
= KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), widget() ? widget()->topLevelWidget()->winId() : 0, KWallet::Wallet::Asynchronous
);
6919 d
->m_wq
= new KHTMLWalletQueue(this);
6920 d
->m_wq
->wallet
= wallet
;
6921 connect(wallet
, SIGNAL(walletOpened(bool)), d
->m_wq
, SLOT(walletOpened(bool)));
6922 connect(d
->m_wq
, SIGNAL(walletOpened(KWallet::Wallet
*)), this, SLOT(walletOpened(KWallet::Wallet
*)));
6924 d
->m_wq
->savers
.append(qMakePair(key
, data
));
6925 #endif // KHTML_NO_WALLET
6929 void KHTMLPart::dequeueWallet(DOM::HTMLFormElementImpl
*form
) {
6930 #ifndef KHTML_NO_WALLET
6933 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart()) {
6937 p
->dequeueWallet(form
);
6942 d
->m_wq
->callers
.removeAll(KHTMLWalletQueue::Caller(form
, form
->document()));
6944 #endif // KHTML_NO_WALLET
6948 void KHTMLPart::walletOpened(KWallet::Wallet
*wallet
) {
6949 #ifndef KHTML_NO_WALLET
6950 assert(!d
->m_wallet
);
6953 d
->m_wq
->deleteLater(); // safe?
6957 d
->m_bWalletOpened
= false;
6961 d
->m_wallet
= wallet
;
6962 d
->m_bWalletOpened
= true;
6963 connect(d
->m_wallet
, SIGNAL(walletClosed()), SLOT(slotWalletClosed()));
6965 if (!d
->m_statusBarWalletLabel
) {
6966 d
->m_statusBarWalletLabel
= new KUrlLabel(d
->m_statusBarExtension
->statusBar());
6967 d
->m_statusBarWalletLabel
->setFixedHeight(KHTMLGlobal::iconLoader()->currentSize(KIconLoader::Small
));
6968 d
->m_statusBarWalletLabel
->setSizePolicy(QSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
));
6969 d
->m_statusBarWalletLabel
->setUseCursor(false);
6970 d
->m_statusBarExtension
->addStatusBarItem(d
->m_statusBarWalletLabel
, 0, false);
6971 d
->m_statusBarWalletLabel
->setPixmap(SmallIcon("wallet-open"));
6972 connect(d
->m_statusBarWalletLabel
, SIGNAL(leftClickedUrl()), SLOT(launchWalletManager()));
6973 connect(d
->m_statusBarWalletLabel
, SIGNAL(rightClickedUrl()), SLOT(walletMenu()));
6975 d
->m_statusBarWalletLabel
->setToolTip(i18n("The wallet '%1' is open and being used for form data and passwords.", KWallet::Wallet::NetworkWallet()));
6976 #endif // KHTML_NO_WALLET
6980 KWallet::Wallet
*KHTMLPart::wallet()
6982 #ifndef KHTML_NO_WALLET
6985 for (p
= parentPart(); p
&& p
->parentPart(); p
= p
->parentPart())
6994 #endif // !KHTML_NO_WALLET
6998 void KHTMLPart::slotWalletClosed()
7000 #ifndef KHTML_NO_WALLET
7002 d
->m_wallet
->deleteLater();
7005 d
->m_bWalletOpened
= false;
7006 if (d
->m_statusBarWalletLabel
) {
7007 d
->m_statusBarExtension
->removeStatusBarItem(d
->m_statusBarWalletLabel
);
7008 delete d
->m_statusBarWalletLabel
;
7009 d
->m_statusBarWalletLabel
= 0L;
7011 #endif // KHTML_NO_WALLET
7014 void KHTMLPart::launchWalletManager()
7016 #ifndef KHTML_NO_WALLET
7017 QDBusInterface
r("org.kde.kwalletmanager", "/kwalletmanager/MainWindow_1",
7018 "org.kde.KMainWindow");
7020 KToolInvocation::startServiceByDesktopName("kwalletmanager_show");
7022 r
.call(QDBus::NoBlock
, "show");
7023 r
.call(QDBus::NoBlock
, "raise");
7025 #endif // KHTML_NO_WALLET
7028 void KHTMLPart::walletMenu()
7030 #ifndef KHTML_NO_WALLET
7031 KMenu
*m
= new KMenu(0L);
7032 m
->addAction(i18n("&Close Wallet"), this, SLOT(slotWalletClosed()));
7033 m
->popup(QCursor::pos());
7034 #endif // KHTML_NO_WALLET
7037 void KHTMLPart::slotToggleCaretMode()
7039 setCaretMode(d
->m_paToggleCaretMode
->isChecked());
7042 void KHTMLPart::setFormNotification(KHTMLPart::FormNotification fn
) {
7043 d
->m_formNotification
= fn
;
7046 KHTMLPart::FormNotification
KHTMLPart::formNotification() const {
7047 return d
->m_formNotification
;
7050 KUrl
KHTMLPart::toplevelURL()
7052 KHTMLPart
* part
= this;
7053 while (part
->parentPart())
7054 part
= part
->parentPart();
7062 bool KHTMLPart::isModified() const
7067 return d
->m_doc
->unsubmittedFormChanges();
7070 void KHTMLPart::setDebugScript( bool enable
)
7072 unplugActionList( "debugScriptList" );
7074 if (!d
->m_paDebugScript
) {
7075 d
->m_paDebugScript
= new KAction( i18n( "JavaScript &Debugger" ), this );
7076 actionCollection()->addAction( "debugScript", d
->m_paDebugScript
);
7077 connect( d
->m_paDebugScript
, SIGNAL( triggered( bool ) ), this, SLOT( slotDebugScript() ) );
7079 d
->m_paDebugScript
->setEnabled( d
->m_frame
? d
->m_frame
->m_jscript
: 0L );
7080 QList
<QAction
*> lst
;
7081 lst
.append( d
->m_paDebugScript
);
7082 plugActionList( "debugScriptList", lst
);
7084 d
->m_bJScriptDebugEnabled
= enable
;
7087 void KHTMLPart::setSuppressedPopupIndicator( bool enable
, KHTMLPart
*originPart
)
7089 if ( parentPart() ) {
7090 parentPart()->setSuppressedPopupIndicator( enable
, originPart
);
7094 if ( enable
&& originPart
) {
7095 d
->m_openableSuppressedPopups
++;
7096 if ( d
->m_suppressedPopupOriginParts
.indexOf( originPart
) == -1 )
7097 d
->m_suppressedPopupOriginParts
.append( originPart
);
7100 if ( enable
&& !d
->m_statusBarPopupLabel
) {
7101 d
->m_statusBarPopupLabel
= new KUrlLabel( d
->m_statusBarExtension
->statusBar() );
7102 d
->m_statusBarPopupLabel
->setFixedHeight( KHTMLGlobal::iconLoader()->currentSize( KIconLoader::Small
) );
7103 d
->m_statusBarPopupLabel
->setSizePolicy( QSizePolicy( QSizePolicy::Fixed
, QSizePolicy::Fixed
));
7104 d
->m_statusBarPopupLabel
->setUseCursor( false );
7105 d
->m_statusBarExtension
->addStatusBarItem( d
->m_statusBarPopupLabel
, 0, false );
7106 d
->m_statusBarPopupLabel
->setPixmap( SmallIcon( "window-suppressed") );
7108 d
->m_statusBarPopupLabel
->setToolTip(i18n("This page was prevented from opening a new window via JavaScript." ) );
7110 connect(d
->m_statusBarPopupLabel
, SIGNAL(leftClickedUrl()), SLOT(suppressedPopupMenu()));
7111 if (d
->m_settings
->jsPopupBlockerPassivePopup()) {
7113 px
= MainBarIcon( "window-suppressed" );
7114 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
);
7116 } else if ( !enable
&& d
->m_statusBarPopupLabel
) {
7117 d
->m_statusBarPopupLabel
->setToolTip("" );
7118 d
->m_statusBarExtension
->removeStatusBarItem( d
->m_statusBarPopupLabel
);
7119 delete d
->m_statusBarPopupLabel
;
7120 d
->m_statusBarPopupLabel
= 0L;
7124 void KHTMLPart::suppressedPopupMenu() {
7125 KMenu
*m
= new KMenu(0L);
7126 if ( d
->m_openableSuppressedPopups
)
7127 m
->addAction(i18np("&Show Blocked Popup Window","&Show %1 Blocked Popup Windows", d
->m_openableSuppressedPopups
), this, SLOT(showSuppressedPopups()));
7128 QAction
*a
= m
->addAction(i18n("Show Blocked Window Passive Popup &Notification"), this, SLOT(togglePopupPassivePopup()));
7129 a
->setChecked(d
->m_settings
->jsPopupBlockerPassivePopup());
7130 m
->addAction(i18n("&Configure JavaScript New Window Policies..."), this, SLOT(launchJSConfigDialog()));
7131 m
->popup(QCursor::pos());
7134 void KHTMLPart::togglePopupPassivePopup() {
7135 // Same hack as in disableJSErrorExtension()
7136 d
->m_settings
->setJSPopupBlockerPassivePopup( !d
->m_settings
->jsPopupBlockerPassivePopup() );
7137 emit
configurationChanged();
7140 void KHTMLPart::showSuppressedPopups() {
7141 foreach ( KHTMLPart
* part
, d
->m_suppressedPopupOriginParts
) {
7143 KJS::Window
*w
= KJS::Window::retrieveWindow( part
);
7145 w
->showSuppressedWindows();
7146 w
->forgetSuppressedWindows();
7150 setSuppressedPopupIndicator( false );
7151 d
->m_openableSuppressedPopups
= 0;
7152 d
->m_suppressedPopupOriginParts
.clear();
7155 // Extension to use for "view document source", "save as" etc.
7156 // Using the right extension can help the viewer get into the right mode (#40496)
7157 QString
KHTMLPart::defaultExtension() const
7161 if ( !d
->m_doc
->isHTMLDocument() )
7163 return d
->m_doc
->htmlMode() == DOM::DocumentImpl::XHtml
? ".xhtml" : ".html";
7166 bool KHTMLPart::inProgress() const
7168 if (!d
->m_bComplete
|| d
->m_runningScripts
|| (d
->m_doc
&& d
->m_doc
->parsing()))
7171 // Any frame that hasn't completed yet ?
7172 ConstFrameIt it
= d
->m_frames
.constBegin();
7173 const ConstFrameIt end
= d
->m_frames
.constEnd();
7174 for (; it
!= end
; ++it
) {
7175 if ((*it
)->m_run
|| !(*it
)->m_bCompleted
)
7179 return d
->m_submitForm
|| !d
->m_redirectURL
.isEmpty() || d
->m_redirectionTimer
.isActive() || d
->m_job
;
7182 using namespace KParts
;
7183 #include "khtml_part.moc"
7184 #include "khtmlpart_p.moc"
7185 #ifndef KHTML_NO_WALLET
7186 #include "khtml_wallet_p.moc"