1 // -*- c-basic-offset: 2 -*-
2 /* This file is part of the KDE project
4 * Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
5 * 1999 Lars Knoll <knoll@kde.org>
6 * 1999 Antti Koivisto <koivisto@kde.org>
7 * 2000 Simon Hausmann <hausmann@kde.org>
8 * 2000 Stefan Schimanski <1Stein@gmx.de>
9 * 2001 George Staikos <staikos@kde.org>
10 * Copyright (C) 2004 Apple Computer, Inc.
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public License
23 * along with this library; see the file COPYING.LIB. If not, write to
24 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
28 #include "khtml_part.h"
31 #define DIRECT_LINKAGE_TO_ECMA
32 #define QT_NO_CLIPBOARD
33 #define QT_NO_DRAGANDDROP
36 #include "khtml_pagecache.h"
38 #include "css/csshelper.h"
39 #include "css/cssproperties.h"
40 #include "css/cssstyleselector.h"
41 #include "css/css_computedstyle.h"
42 #include "css/css_valueimpl.h"
43 #include "dom/dom_string.h"
44 #include "dom/dom_element.h"
45 #include "dom/html_document.h"
46 #include "editing/markup.h"
47 #include "editing/selection.h"
48 #include "editing/visible_position.h"
49 #include "editing/visible_text.h"
50 #include "editing/visible_units.h"
51 #include "html/html_documentimpl.h"
52 #include "html/html_baseimpl.h"
53 #include "html/html_miscimpl.h"
54 #include "html/html_imageimpl.h"
55 #include "html/html_objectimpl.h"
56 #include "rendering/render_block.h"
57 #include "rendering/render_text.h"
58 #include "rendering/render_frames.h"
59 #include "misc/htmlhashes.h"
60 #include "misc/loader.h"
61 #include "xml/dom2_eventsimpl.h"
62 #include "xml/dom2_rangeimpl.h"
63 #include "xml/xml_tokenizer.h"
67 #include "khtmlview.h"
68 #include <kparts/partmanager.h>
69 #include "ecma/kjs_proxy.h"
70 #include "khtml_settings.h"
72 #include <sys/types.h>
76 #include <kstandarddirs.h>
78 #include <kio/global.h>
80 #include <kiconloader.h>
82 #include <kcharsets.h>
83 #include <kmessagebox.h>
84 #include <kstdaction.h>
85 #include <kfiledialog.h>
87 #include <kdatastream.h>
88 #include <ktempfile.h>
89 #include <kglobalsettings.h>
91 #include <kapplication.h>
92 #if !defined(QT_NO_DRAGANDDROP)
93 #include <kmultipledrag.h>
96 #include <ksslcertchain.h>
97 #include <ksslinfodlg.h>
99 #include <qclipboard.h>
101 #include <qmetaobject.h>
102 #include <qptrlist.h>
103 #include <private/qucomextra_p.h>
105 #include "khtmlpart_p.h"
108 #include <CoreServices/CoreServices.h>
111 using khtml::ApplyStyleCommand;
112 using khtml::CHARACTER;
113 using khtml::ChildFrame;
114 using khtml::Decoder;
115 using khtml::EAffinity;
116 using khtml::EditAction;
117 using khtml::EditCommandPtr;
118 using khtml::ETextGranularity;
119 using khtml::FormData;
120 using khtml::InlineTextBox;
121 using khtml::isEndOfDocument;
122 using khtml::isStartOfDocument;
123 using khtml::PARAGRAPH;
124 using khtml::plainText;
125 using khtml::RenderObject;
126 using khtml::RenderText;
127 using khtml::RenderWidget;
128 using khtml::Selection;
129 using khtml::Tokenizer;
130 using khtml::TypingCommand;
131 using khtml::VisiblePosition;
134 using KParts::BrowserInterface;
136 const int CARET_BLINK_FREQUENCY = 500;
139 class PartStyleSheetLoader : public CachedObjectClient
142 PartStyleSheetLoader(KHTMLPart *part, DOM::DOMString url, DocLoader* dl)
145 m_cachedSheet = Cache::requestStyleSheet(dl, url );
147 m_cachedSheet->ref( this );
149 virtual ~PartStyleSheetLoader()
151 if ( m_cachedSheet ) m_cachedSheet->deref(this);
153 virtual void setStyleSheet(const DOM::DOMString&, const DOM::DOMString &sheet)
156 m_part->setUserStyleSheet( sheet.string() );
160 QGuardedPtr<KHTMLPart> m_part;
161 khtml::CachedCSSStyleSheet *m_cachedSheet;
165 FrameList::Iterator FrameList::find( const QString &name )
167 Iterator it = begin();
171 if ( (*it).m_name==name )
177 KHTMLPart::KHTMLPart( QWidget *parentWidget, const char *widgetname, QObject *parent, const char *name,
179 : KParts::ReadOnlyPart( parent, name )
182 KHTMLFactory::registerPart( this );
183 setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
185 init( new KHTMLView( this, parentWidget, widgetname ), prof );
191 KHTMLPart::KHTMLPart( KHTMLView *view, QObject *parent, const char *name, GUIProfile prof )
192 : KParts::ReadOnlyPart( parent, name )
195 KHTMLFactory::registerPart( this );
196 setInstance( KHTMLFactory::instance(), prof == BrowserViewGUI && !parentPart() );
201 #endif // APPLE_CHANGES
203 void KHTMLPart::init( KHTMLView *view, GUIProfile prof )
205 AtomicString::init();
206 if ( prof == DefaultGUI )
207 setXMLFile( "khtml.rc" );
208 else if ( prof == BrowserViewGUI )
209 setXMLFile( "khtml_browser.rc" );
213 d = new KHTMLPartPrivate(parent());
216 setWidget( d->m_view );
219 d->m_guiProfile = prof;
221 d->m_extension = new KHTMLPartBrowserExtension( this );
222 d->m_hostExtension = new KHTMLPartBrowserHostExtension( this );
224 d->m_bSecurityInQuestion = false;
225 d->m_bMousePressed = false;
227 d->m_paLoadImages = 0;
228 d->m_paViewDocument = new KAction( i18n( "View Document Source" ), 0, this, SLOT( slotViewDocumentSource() ), actionCollection(), "viewDocumentSource" );
229 d->m_paViewFrame = new KAction( i18n( "View Frame Source" ), 0, this, SLOT( slotViewFrameSource() ), actionCollection(), "viewFrameSource" );
230 d->m_paSaveBackground = new KAction( i18n( "Save &Background Image As..." ), 0, this, SLOT( slotSaveBackground() ), actionCollection(), "saveBackground" );
231 d->m_paSaveDocument = new KAction( i18n( "&Save As..." ), CTRL+Key_S, this, SLOT( slotSaveDocument() ), actionCollection(), "saveDocument" );
233 d->m_paSaveDocument->setShortcut( KShortcut() ); // avoid clashes
234 d->m_paSaveFrame = new KAction( i18n( "Save &Frame As..." ), 0, this, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
235 d->m_paSecurity = new KAction( i18n( "Security..." ), "decrypted", 0, this, SLOT( slotSecurity() ), actionCollection(), "security" );
236 d->m_paDebugRenderTree = new KAction( "print rendering tree to stdout", 0, this, SLOT( slotDebugRenderTree() ), actionCollection(), "debugRenderTree" );
237 d->m_paDebugDOMTree = new KAction( "print DOM tree to stdout", 0, this, SLOT( slotDebugDOMTree() ), actionCollection(), "debugDOMTree" );
239 QString foo1 = i18n("Show Images");
240 QString foo2 = i18n("Show Animated Images");
241 QString foo3 = i18n("Stop Animated Images");
243 d->m_paSetEncoding = new KSelectAction( i18n( "Set &Encoding" ), 0, this, SLOT( slotSetEncoding() ), actionCollection(), "setEncoding" );
244 QStringList encodings = KGlobal::charsets()->descriptiveEncodingNames();
245 encodings.prepend( i18n( "Auto" ) );
246 d->m_paSetEncoding->setItems( encodings );
247 d->m_paSetEncoding->setCurrentItem(0);
249 d->m_paUseStylesheet = new KSelectAction( i18n( "&Use Stylesheet"), 0, this, SLOT( slotUseStylesheet() ), actionCollection(), "useStylesheet" );
251 d->m_paIncZoomFactor = new KHTMLZoomFactorAction( this, true, i18n( "Increase Font Sizes" ), "viewmag+", this, SLOT( slotIncZoom() ), actionCollection(), "incFontSizes" );
252 d->m_paDecZoomFactor = new KHTMLZoomFactorAction( this, false, i18n( "Decrease Font Sizes" ), "viewmag-", this, SLOT( slotDecZoom() ), actionCollection(), "decFontSizes" );
254 d->m_paFind = KStdAction::find( this, SLOT( slotFind() ), actionCollection(), "find" );
256 d->m_paFind->setShortcut( KShortcut() ); // avoid clashes
258 d->m_paPrintFrame = new KAction( i18n( "Print Frame" ), "frameprint", 0, this, SLOT( slotPrintFrame() ), actionCollection(), "printFrame" );
260 d->m_paSelectAll = KStdAction::selectAll( this, SLOT( slotSelectAll() ), actionCollection(), "selectAll" );
262 d->m_paSelectAll->setShortcut( KShortcut() ); // avoid clashes
266 // set the default java(script) flags according to the current host.
267 d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled();
268 d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
269 d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled();
270 d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled();
272 // The java, javascript, and plugin settings will be set after the settings
273 // have been initialized.
274 d->m_bJScriptEnabled = true;
275 d->m_bJScriptDebugEnabled = true;
276 d->m_bJavaEnabled = true;
277 d->m_bPluginsEnabled = true;
281 connect( this, SIGNAL( completed() ),
282 this, SLOT( updateActions() ) );
283 connect( this, SIGNAL( completed( bool ) ),
284 this, SLOT( updateActions() ) );
285 connect( this, SIGNAL( started( KIO::Job * ) ),
286 this, SLOT( updateActions() ) );
288 d->m_popupMenuXML = KXMLGUIFactory::readConfigFile( locate( "data", "khtml/khtml_popupmenu.rc", KHTMLFactory::instance() ) );
291 connect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
292 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
293 connect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
294 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
295 connect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
296 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
299 findTextBegin(); //reset find variables
302 connect( &d->m_redirectionTimer, SIGNAL( timeout() ),
303 this, SLOT( slotRedirect() ) );
305 connect(&d->m_lifeSupportTimer, SIGNAL(timeout()), this, SLOT(slotEndLifeSupport()));
308 d->m_dcopobject = new KHTMLPartIface(this);
312 KHTMLPart::~KHTMLPart()
314 //kdDebug(6050) << "KHTMLPart::~KHTMLPart " << this << endl;
316 if ( d->m_findDialog )
317 disconnect( d->m_findDialog, SIGNAL( destroyed() ),
318 this, SLOT( slotFindDialogDestroyed() ) );
322 d->m_manager->setActivePart( 0 );
323 // Shouldn't we delete d->m_manager here ? (David)
324 // No need to, I would say. We specify "this" as parent qobject
325 // in ::partManager() (Simon)
335 disconnect( khtml::Cache::loader(), SIGNAL( requestStarted( khtml::DocLoader*, khtml::CachedObject* ) ),
336 this, SLOT( slotLoaderRequestStarted( khtml::DocLoader*, khtml::CachedObject* ) ) );
337 disconnect( khtml::Cache::loader(), SIGNAL( requestDone( khtml::DocLoader*, khtml::CachedObject *) ),
338 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
339 disconnect( khtml::Cache::loader(), SIGNAL( requestFailed( khtml::DocLoader*, khtml::CachedObject *) ),
340 this, SLOT( slotLoaderRequestDone( khtml::DocLoader*, khtml::CachedObject *) ) );
347 d->m_view->viewport()->hide();
348 d->m_view->m_part = 0;
352 delete d->m_hostExtension;
356 KHTMLFactory::deregisterPart( this );
359 bool KHTMLPart::restoreURL( const KURL &url )
361 kdDebug( 6050 ) << "KHTMLPart::restoreURL " << url.url() << endl;
366 * That's not a good idea as it will call closeURL() on all
367 * child frames, preventing them from further loading. This
368 * method gets called from restoreState() in case of a full frameset
369 * restoral, and restoreState() calls closeURL() before restoring
371 kdDebug( 6050 ) << "closing old URL" << endl;
375 d->m_bComplete = false;
376 d->m_bLoadEventEmitted = false;
377 d->m_workingURL = url;
379 // set the java(script) flags according to the current host.
381 d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
382 d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
383 d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
384 d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
386 d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(url.host());
387 d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
388 d->m_bJavaEnabled = d->m_settings->isJavaEnabled(url.host());
389 d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(url.host());
394 KHTMLPageCache::self()->fetchData( d->m_cacheId, this, SLOT(slotRestoreData(const QByteArray &)));
403 bool KHTMLPart::didOpenURL(const KURL &url)
405 bool KHTMLPart::openURL( const KURL &url )
408 kdDebug( 6050 ) << "KHTMLPart(" << this << ")::openURL " << url.url() << endl;
410 if (d->m_scheduledRedirection == locationChangeScheduledDuringLoad) {
411 // We're about to get a redirect that happened before the document was
412 // created. This can happen when one frame may change the location of a
419 // clear last edit command
420 d->m_lastEditCommand = EditCommandPtr();
422 KWQ(this)->clearUndoRedoOperations();
426 // check to see if this is an "error://" URL. This is caused when an error
427 // occurs before this part was loaded (e.g. KonqRun), and is passed to
428 // khtmlpart so that it can display the error.
429 if ( url.protocol() == "error" && url.hasSubURL() ) {
432 * The format of the error url is that two variables are passed in the query:
433 * error = int kio error code, errText = QString error text from kio
434 * and the URL where the error happened is passed as a sub URL.
436 KURL::List urls = KURL::split( url );
437 //kdDebug() << "Handling error URL. URL count:" << urls.count() << endl;
439 if ( urls.count() > 1 ) {
440 KURL mainURL = urls.first();
441 int error = mainURL.queryItem( "error" ).toInt();
442 // error=0 isn't a valid error code, so 0 means it's missing from the URL
443 if ( error == 0 ) error = KIO::ERR_UNKNOWN;
444 QString errorText = mainURL.queryItem( "errText" );
446 d->m_workingURL = KURL::join( urls );
447 //kdDebug() << "Emitting fixed URL " << d->m_workingURL.prettyURL() << endl;
448 emit d->m_extension->setLocationBarURL( d->m_workingURL.prettyURL() );
449 htmlError( error, errorText, d->m_workingURL );
453 #endif // APPLE_CHANGES
455 KParts::URLArgs args( d->m_extension->urlArgs() );
458 // in case we have a) no frameset (don't test m_frames.count(), iframes get in there)
459 // b) the url is identical with the currently
460 // displayed one (except for the htmlref!) , c) the url request is not a POST
461 // operation and d) the caller did not request to reload the page we try to
462 // be smart and instead of reloading the whole document we just jump to the
463 // request html anchor
465 bool isFrameSet = false;
466 if ( d->m_doc->isHTMLDocument() ) {
467 HTMLDocumentImpl* htmlDoc = static_cast<HTMLDocumentImpl*>(d->m_doc);
468 isFrameSet = htmlDoc->body() && (htmlDoc->body()->id() == ID_FRAMESET);
471 urlcmp( url.url(), m_url.url(), true, true ) &&
472 url.hasRef() && !args.doPost() && !args.reload )
474 kdDebug( 6050 ) << "KHTMLPart::openURL, jumping to anchor. m_url = " << url.url() << endl;
480 d->m_bComplete = true;
481 d->m_doc->setParsing(false);
483 kdDebug( 6050 ) << "completed..." << endl;
488 #endif // APPLE_CHANGES
492 kdDebug( 6050 ) << "closing old URL" << endl;
497 args.metaData().insert("main_frame_request", parentPart() == 0 ? "TRUE" : "FALSE" );
498 args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE" : "FALSE" );
499 args.metaData().insert("ssl_activate_warnings", "TRUE" );
503 d->m_cachePolicy = KIO::CC_Cache;
504 else if (args.reload)
505 d->m_cachePolicy = KIO::CC_Refresh;
507 d->m_cachePolicy = KIO::CC_Verify;
509 if ( args.doPost() && (url.protocol().startsWith("http")) )
511 d->m_job = KIO::http_post( url, args.postData, false );
512 d->m_job->addMetaData("content-type", args.contentType() );
516 d->m_job = KIO::get( url, false, false );
517 d->m_job->addMetaData("cache", KIO::getCacheControlString(d->m_cachePolicy));
520 d->m_job->addMetaData(args.metaData());
522 connect( d->m_job, SIGNAL( result( KIO::Job * ) ),
523 SLOT( slotFinished( KIO::Job * ) ) );
525 connect( d->m_job, SIGNAL( data( KIO::Job*, const QByteArray &)),
526 SLOT( slotData( KIO::Job*, const QByteArray &)));
529 connect( d->m_job, SIGNAL(redirection(KIO::Job*, const KURL&) ),
530 SLOT( slotRedirection(KIO::Job*,const KURL&) ) );
532 d->m_bComplete = false;
533 d->m_bLoadingMainResource = true;
534 d->m_bLoadEventEmitted = false;
536 // delete old status bar msg's from kjs (if it _was_ activated on last URL)
537 if( d->m_bJScriptEnabled )
539 d->m_kjsStatusBarText = QString::null;
540 d->m_kjsDefaultStatusBarText = QString::null;
543 // set the javascript flags according to the current url
545 d->m_bJScriptDebugEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptDebugEnabled();
546 d->m_bJavaEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaEnabled(url.host());
547 d->m_bPluginsEnabled = KHTMLFactory::defaultHTMLSettings()->isPluginsEnabled(url.host());
549 d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
550 d->m_bJavaEnabled = d->m_settings->isJavaEnabled(url.host());
551 d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(url.host());
554 // 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
555 // data arrives) (Simon)
557 if(m_url.protocol().startsWith( "http" ) && !m_url.host().isEmpty() &&
558 m_url.path().isEmpty()) {
560 emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
562 // copy to m_workingURL after fixing m_url above
563 d->m_workingURL = m_url;
565 kdDebug( 6050 ) << "KHTMLPart::openURL now (before started) m_url = " << m_url.url() << endl;
567 connect( d->m_job, SIGNAL( speed( KIO::Job*, unsigned long ) ),
568 this, SLOT( slotJobSpeed( KIO::Job*, unsigned long ) ) );
570 connect( d->m_job, SIGNAL( percent( KIO::Job*, unsigned long ) ),
571 this, SLOT( slotJobPercent( KIO::Job*, unsigned long ) ) );
578 void KHTMLPart::didExplicitOpen()
580 d->m_bComplete = false;
581 d->m_bLoadEventEmitted = false;
585 bool KHTMLPart::closeURL()
587 if (d->m_doc && d->m_doc->tokenizer()) {
588 d->m_doc->tokenizer()->stopParsing();
593 KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
598 if ( d->m_doc && d->m_doc->isHTMLDocument() ) {
599 HTMLDocumentImpl* hdoc = static_cast<HTMLDocumentImpl*>( d->m_doc );
601 if ( hdoc->body() && d->m_bLoadEventEmitted && !d->m_bUnloadEventEmitted ) {
602 hdoc->body()->dispatchWindowEvent( EventImpl::UNLOAD_EVENT, false, false );
604 d->m_doc->updateRendering();
605 d->m_bUnloadEventEmitted = true;
609 d->m_bComplete = true; // to avoid emitting completed() in slotFinishedParsing() (David)
610 d->m_bLoadingMainResource = false;
611 d->m_bLoadEventEmitted = true; // don't want that one either
612 d->m_cachePolicy = KIO::CC_Verify; // Why here?
614 KHTMLPageCache::self()->cancelFetch(this);
615 if ( d->m_doc && d->m_doc->parsing() )
617 kdDebug( 6050 ) << " was still parsing... calling end " << endl;
618 slotFinishedParsing();
619 d->m_doc->setParsing(false);
622 if ( !d->m_workingURL.isEmpty() )
624 // Aborted before starting to render
625 kdDebug( 6050 ) << "Aborted before starting to render, reverting location bar to " << m_url.prettyURL() << endl;
626 emit d->m_extension->setLocationBarURL( m_url.prettyURL() );
629 d->m_workingURL = KURL();
631 if ( d->m_doc && d->m_doc->docLoader() )
632 khtml::Cache::loader()->cancelRequests( d->m_doc->docLoader() );
634 // tell all subframes to stop as well
635 ConstFrameIt it = d->m_frames.begin();
636 ConstFrameIt end = d->m_frames.end();
637 for (; it != end; ++it )
638 if ( !( *it ).m_part.isNull() )
639 ( *it ).m_part->closeURL();
641 d->m_bPendingChildRedirection = false;
643 // Stop any started redirections as well!! (DA)
646 // null node activated.
647 emit nodeActivated(Node());
652 DOM::HTMLDocument KHTMLPart::htmlDocument() const
654 if (d->m_doc && d->m_doc->isHTMLDocument())
655 return static_cast<HTMLDocumentImpl*>(d->m_doc);
657 return static_cast<HTMLDocumentImpl*>(0);
660 DOM::Document KHTMLPart::document() const
666 KParts::BrowserExtension *KHTMLPart::browserExtension() const
668 return d->m_extension;
671 KHTMLView *KHTMLPart::view() const
676 void KHTMLPart::setJScriptEnabled( bool enable )
678 if ( !enable && jScriptEnabled() && d->m_jscript ) {
679 d->m_jscript->clear();
681 d->m_bJScriptForce = enable;
682 d->m_bJScriptOverride = true;
685 bool KHTMLPart::jScriptEnabled() const
687 if ( d->m_bJScriptOverride )
688 return d->m_bJScriptForce;
689 return d->m_bJScriptEnabled;
692 void KHTMLPart::setMetaRefreshEnabled( bool enable )
694 d->m_metaRefreshEnabled = enable;
697 bool KHTMLPart::metaRefreshEnabled() const
699 return d->m_metaRefreshEnabled;
702 // Define this to disable dlopening kjs_html, when directly linking to it.
703 // You need to edit khtml/Makefile.am to add ./ecma/libkjs_html.la to LIBADD
704 // and to edit khtml/ecma/Makefile.am to s/kjs_html/libkjs_html/, remove libkhtml from LIBADD,
705 // remove LDFLAGS line, and replace kde_module with either lib (shared) or noinst (static)
706 //#define DIRECT_LINKAGE_TO_ECMA
708 #ifdef DIRECT_LINKAGE_TO_ECMA
709 extern "C" { KJSProxy *kjs_html_init(KHTMLPart *khtmlpart); }
712 KJSProxy *KHTMLPart::jScript()
714 if (!jScriptEnabled()){
720 #ifndef DIRECT_LINKAGE_TO_ECMA
721 KLibrary *lib = KLibLoader::self()->library("kjs_html");
723 setJScriptEnabled( false );
726 // look for plain C init function
727 void *sym = lib->symbol("kjs_html_init");
730 setJScriptEnabled( false );
733 typedef KJSProxy* (*initFunction)(KHTMLPart *);
734 initFunction initSym = (initFunction) sym;
735 d->m_jscript = (*initSym)(this);
738 d->m_jscript = kjs_html_init(this);
739 // d->m_kjs_lib remains 0L.
741 if (d->m_bJScriptDebugEnabled)
742 d->m_jscript->setDebugEnabled(true);
748 void KHTMLPart::replaceContentsWithScriptResult( const KURL &url )
750 QString script = KURL::decode_string(url.url().mid(strlen("javascript:")));
751 QVariant ret = executeScript(script);
753 if (ret.type() == QVariant::String) {
755 write(ret.asString());
760 QVariant KHTMLPart::executeScript( const QString &script, bool forceUserGesture )
762 return executeScript( DOM::Node(), script, forceUserGesture );
765 //Enable this to see all JS scripts being executed
766 //#define KJS_VERBOSE
768 QVariant KHTMLPart::executeScript( const DOM::Node &n, const QString &script, bool forceUserGesture )
771 kdDebug(6070) << "KHTMLPart::executeScript n=" << n.nodeName().string().latin1() << "(" << (n.isNull() ? 0 : n.nodeType()) << ") " << script << endl;
773 KJSProxy *proxy = jScript();
775 if (!proxy || proxy->paused())
777 d->m_runningScripts++;
778 // If forceUserGesture is true, then make the script interpreter
779 // treat it as if triggered by a user gesture even if there is no
780 // current DOM event being processed.
781 QVariant ret = proxy->evaluate( forceUserGesture ? QString::null : m_url.url(), 0, script, n );
782 d->m_runningScripts--;
783 if (!d->m_runningScripts && d->m_doc && !d->m_doc->parsing() && d->m_submitForm )
785 DocumentImpl::updateDocumentsRendering();
788 kdDebug(6070) << "KHTMLPart::executeScript - done" << endl;
793 bool KHTMLPart::scheduleScript(const DOM::Node &n, const QString& script)
795 //kdDebug(6050) << "KHTMLPart::scheduleScript "<< script << endl;
797 d->scheduledScript = script;
798 d->scheduledScriptNode = n;
803 QVariant KHTMLPart::executeScheduledScript()
805 if( d->scheduledScript.isEmpty() )
808 //kdDebug(6050) << "executing delayed " << d->scheduledScript << endl;
810 QVariant ret = executeScript( d->scheduledScriptNode, d->scheduledScript );
811 d->scheduledScript = QString();
812 d->scheduledScriptNode = DOM::Node();
817 void KHTMLPart::setJavaEnabled( bool enable )
819 d->m_bJavaForce = enable;
820 d->m_bJavaOverride = true;
823 bool KHTMLPart::javaEnabled() const
826 if( d->m_bJavaOverride )
827 return d->m_bJavaForce;
828 return d->m_bJavaEnabled;
834 KJavaAppletContext *KHTMLPart::javaContext()
837 return d->m_javaContext;
843 KJavaAppletContext *KHTMLPart::createJavaContext()
846 if ( !d->m_javaContext ) {
848 d->m_javaContext = new KJavaAppletContext(d->m_dcopobject, this);
850 d->m_javaContext = new KJavaAppletContext(d->m_dcopobject);
851 connect( d->m_javaContext, SIGNAL(showStatus(const QString&)),
852 this, SIGNAL(setStatusBarText(const QString&)) );
853 connect( d->m_javaContext, SIGNAL(showDocument(const QString&, const QString&)),
854 this, SLOT(slotShowDocument(const QString&, const QString&)) );
858 return d->m_javaContext;
864 void KHTMLPart::setPluginsEnabled( bool enable )
866 d->m_bPluginsForce = enable;
867 d->m_bPluginsOverride = true;
870 bool KHTMLPart::pluginsEnabled() const
872 if ( d->m_bPluginsOverride )
873 return d->m_bPluginsForce;
874 return d->m_bPluginsEnabled;
879 void KHTMLPart::slotShowDocument( const QString &url, const QString &target )
881 // this is mostly copied from KHTMLPart::slotChildURLRequest. The better approach
882 // would be to put those functions into a single one.
883 khtml::ChildFrame *child = 0;
884 KParts::URLArgs args;
885 args.frameName = target;
887 QString frameName = args.frameName.lower();
888 if ( !frameName.isEmpty() )
890 if ( frameName == QString::fromLatin1( "_top" ) )
892 emit d->m_extension->openURLRequest( url, args );
895 else if ( frameName == QString::fromLatin1( "_blank" ) )
897 emit d->m_extension->createNewWindow( url, args );
900 else if ( frameName == QString::fromLatin1( "_parent" ) )
902 KParts::URLArgs newArgs( args );
903 newArgs.frameName = QString::null;
905 emit d->m_extension->openURLRequest( url, newArgs );
908 else if ( frameName != QString::fromLatin1( "_self" ) )
910 khtml::ChildFrame *_frame = recursiveFrameRequest( url, args );
914 emit d->m_extension->openURLRequest( url, args );
922 // TODO: handle child target correctly! currently the script are always executed fur the parent
923 if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
924 executeScript( KURL::decode_string( url.right( url.length() - 11) ) );
929 requestObject( child, KURL(url), args );
930 } else if ( frameName==QString::fromLatin1("_self") ) // this is for embedded objects (via <object>) which want to replace the current document
932 KParts::URLArgs newArgs( args );
933 newArgs.frameName = QString::null;
934 emit d->m_extension->openURLRequest( KURL(url), newArgs );
938 #endif // APPLE_CHANGES
940 void KHTMLPart::slotDebugDOMTree()
942 if ( d->m_doc && d->m_doc->firstChild() )
943 qDebug("%s", createMarkup(d->m_doc->firstChild()).latin1());
946 void KHTMLPart::slotDebugRenderTree()
950 d->m_doc->renderer()->printTree();
954 void KHTMLPart::setAutoloadImages( bool enable )
956 if ( d->m_doc && d->m_doc->docLoader()->autoloadImages() == enable )
960 d->m_doc->docLoader()->setAutoloadImages( enable );
963 unplugActionList( "loadImages" );
966 delete d->m_paLoadImages;
967 d->m_paLoadImages = 0;
969 else if ( !d->m_paLoadImages )
970 d->m_paLoadImages = new KAction( i18n( "Display Images on Page" ), "images_display", 0, this, SLOT( slotLoadImages() ), actionCollection(), "loadImages" );
972 if ( d->m_paLoadImages ) {
973 QPtrList<KAction> lst;
974 lst.append( d->m_paLoadImages );
975 plugActionList( "loadImages", lst );
980 bool KHTMLPart::autoloadImages() const
983 return d->m_doc->docLoader()->autoloadImages();
988 void KHTMLPart::clear()
992 d->m_bCleared = true;
994 d->m_bClearing = true;
998 ConstFrameIt it = d->m_frames.begin();
999 ConstFrameIt end = d->m_frames.end();
1000 for(; it != end; ++it )
1002 // Stop HTMLRun jobs for frames
1004 (*it).m_run->abort();
1009 QValueList<khtml::ChildFrame>::ConstIterator it = d->m_objects.begin();
1010 QValueList<khtml::ChildFrame>::ConstIterator end = d->m_objects.end();
1011 for(; it != end; ++it )
1013 // Stop HTMLRun jobs for objects
1015 (*it).m_run->abort();
1020 findTextBegin(); // resets d->m_findNode and d->m_findPos
1023 d->m_mousePressNode = DOM::Node();
1029 // Moving past doc so that onUnload works.
1031 d->m_jscript->clear();
1036 // do not dereference the document before the jscript and view are cleared, as some destructors
1037 // might still try to access the document.
1043 d->m_decoder->deref();
1047 ConstFrameIt it = d->m_frames.begin();
1048 ConstFrameIt end = d->m_frames.end();
1049 for(; it != end; ++it )
1053 disconnectChild(&*it);
1055 partManager()->removePart( (*it).m_part );
1057 (*it).m_part->deref();
1061 d->m_frames.clear();
1064 ConstFrameIt it = d->m_objects.begin();
1065 ConstFrameIt end = d->m_objects.end();
1066 for(; it != end; ++it )
1071 partManager()->removePart( (*it).m_part );
1073 (*it).m_part->deref();
1077 d->m_objects.clear();
1080 delete d->m_javaContext;
1081 d->m_javaContext = 0;
1084 d->m_scheduledRedirection = noRedirectionScheduled;
1085 d->m_delayRedirect = 0;
1086 d->m_redirectURL = QString::null;
1087 d->m_redirectReferrer = QString::null;
1088 d->m_redirectLockHistory = true;
1089 d->m_redirectUserGesture = false;
1090 d->m_bHTTPRefresh = false;
1091 d->m_bClearing = false;
1092 d->m_frameNameId = 1;
1093 d->m_bFirstData = true;
1095 d->m_bMousePressed = false;
1097 #ifndef QT_NO_CLIPBOARD
1098 connect( kapp->clipboard(), SIGNAL( selectionChanged()), SLOT( slotClearSelection()));
1102 d->m_totalObjectCount = 0;
1103 d->m_loadedObjects = 0;
1104 d->m_jobPercent = 0;
1107 if ( !d->m_haveEncoding )
1108 d->m_encoding = QString::null;
1110 d->m_parsetime.restart();
1114 bool KHTMLPart::openFile()
1119 DOM::DocumentImpl *KHTMLPart::xmlDocImpl() const
1126 void KHTMLPart::replaceDocImpl(DocumentImpl* newDoc)
1139 /*bool KHTMLPart::isSSLInUse() const
1141 return d->m_ssl_in_use;
1144 void KHTMLPart::receivedFirstData()
1146 // Leave indented one extra for easier merging.
1148 //kdDebug( 6050 ) << "begin!" << endl;
1150 begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
1153 d->m_doc->docLoader()->setCachePolicy(d->m_cachePolicy);
1154 d->m_workingURL = KURL();
1156 d->m_cacheId = KHTMLPageCache::self()->createCacheEntry();
1158 // When the first data arrives, the metadata has just been made available
1162 d->m_bSecurityInQuestion = false;
1163 d->m_ssl_in_use = (d->m_job->queryMetaData("ssl_in_use") == "TRUE");
1164 kdDebug(6050) << "SSL in use? " << d->m_job->queryMetaData("ssl_in_use") << endl;
1167 KHTMLPart *p = parentPart();
1168 if (p && p->d->m_ssl_in_use != d->m_ssl_in_use) {
1169 while (p->parentPart()) p = p->parentPart();
1171 p->d->m_paSecurity->setIcon( "halfencrypted" );
1172 p->d->m_bSecurityInQuestion = true;
1173 kdDebug(6050) << "parent setIcon half done." << endl;
1177 d->m_paSecurity->setIcon( d->m_ssl_in_use ? "encrypted" : "decrypted" );
1178 kdDebug(6050) << "setIcon " << ( d->m_ssl_in_use ? "encrypted" : "decrypted" ) << " done." << endl;
1180 // Shouldn't all of this be done only if ssl_in_use == true ? (DF)
1182 d->m_ssl_peer_certificate = d->m_job->queryMetaData("ssl_peer_certificate");
1183 d->m_ssl_peer_chain = d->m_job->queryMetaData("ssl_peer_chain");
1184 d->m_ssl_peer_ip = d->m_job->queryMetaData("ssl_peer_ip");
1185 d->m_ssl_cipher = d->m_job->queryMetaData("ssl_cipher");
1186 d->m_ssl_cipher_desc = d->m_job->queryMetaData("ssl_cipher_desc");
1187 d->m_ssl_cipher_version = d->m_job->queryMetaData("ssl_cipher_version");
1188 d->m_ssl_cipher_used_bits = d->m_job->queryMetaData("ssl_cipher_used_bits");
1189 d->m_ssl_cipher_bits = d->m_job->queryMetaData("ssl_cipher_bits");
1190 d->m_ssl_cert_state = d->m_job->queryMetaData("ssl_cert_state");
1192 // Check for charset meta-data
1193 QString qData = d->m_job->queryMetaData("charset");
1194 if ( !qData.isEmpty() && !d->m_haveEncoding ) // only use information if the user didn't override the settings
1195 d->m_encoding = qData;
1196 #endif // APPLE_CHANGES
1198 // Support for http-refresh
1199 qData = d->m_job->queryMetaData("http-refresh");
1200 if( !qData.isEmpty() && d->m_metaRefreshEnabled )
1202 kdDebug(6050) << "HTTP Refresh Request: " << qData << endl;
1204 int pos = qData.find( ';' );
1206 pos = qData.find( ',' );
1210 delay = qData.stripWhiteSpace().toDouble();
1212 // We want a new history item if the refresh timeout > 1 second
1213 scheduleRedirection( delay, m_url.url(), delay <= 1);
1215 scheduleRedirection( delay, m_url.url());
1220 int end_pos = qData.length();
1221 delay = qData.left(pos).stripWhiteSpace().toDouble();
1222 while ( qData[++pos] == ' ' );
1223 if ( qData.find( "url", pos, false ) == pos )
1226 while (qData[pos] == ' ' || qData[pos] == '=' )
1228 if ( qData[pos] == '"' )
1231 int index = end_pos-1;
1232 while( index > pos )
1234 if ( qData[index] == '"' )
1243 // We want a new history item if the refresh timeout > 1 second
1244 scheduleRedirection( delay, d->m_doc->completeURL( qData.mid( pos, end_pos ) ), delay <= 1);
1246 scheduleRedirection( delay, d->m_doc->completeURL( qData.mid( pos, end_pos ) ));
1249 d->m_bHTTPRefresh = true;
1252 // Support for http last-modified
1253 d->m_lastModified = d->m_job->queryMetaData("modified");
1254 //kdDebug() << "KHTMLPart::slotData metadata modified: " << d->m_lastModified << endl;
1259 void KHTMLPart::slotData( KIO::Job* kio_job, const QByteArray &data )
1261 assert ( d->m_job == kio_job );
1263 //kdDebug( 6050 ) << "slotData: " << data.size() << endl;
1265 if ( !d->m_workingURL.isEmpty() )
1266 receivedFirstData( );
1268 KHTMLPageCache::self()->addData(d->m_cacheId, data);
1269 write( data.data(), data.size() );
1272 void KHTMLPart::slotRestoreData(const QByteArray &data )
1275 if ( !d->m_workingURL.isEmpty() )
1277 long saveCacheId = d->m_cacheId;
1278 begin( d->m_workingURL, d->m_extension->urlArgs().xOffset, d->m_extension->urlArgs().yOffset );
1279 d->m_cacheId = saveCacheId;
1280 d->m_workingURL = KURL();
1283 //kdDebug( 6050 ) << "slotRestoreData: " << data.size() << endl;
1284 write( data.data(), data.size() );
1286 if (data.size() == 0)
1288 //kdDebug( 6050 ) << "slotRestoreData: <<end of data>>" << endl;
1290 if (d->m_doc && d->m_doc->parsing())
1291 end(); //will emit completed()
1295 void KHTMLPart::showError( KIO::Job* job )
1297 kdDebug() << "KHTMLPart::showError d->m_bParsing=" << (d->m_doc && d->m_doc->parsing()) << " d->m_bComplete=" << d->m_bComplete
1298 << " d->m_bCleared=" << d->m_bCleared << endl;
1300 if (job->error() == KIO::ERR_NO_CONTENT)
1303 if ( (d->m_doc && d->m_doc->parsing()) || d->m_workingURL.isEmpty() ) // if we got any data already
1304 job->showErrorDialog( /*d->m_view*/ );
1307 htmlError( job->error(), job->errorText(), d->m_workingURL );
1311 // This is a protected method, placed here because of it's relevance to showError
1312 void KHTMLPart::htmlError( int errorCode, const QString& text, const KURL& reqUrl )
1314 kdDebug(6050) << "KHTMLPart::htmlError errorCode=" << errorCode << " text=" << text << endl;
1315 // make sure we're not executing any embedded JS
1316 bool bJSFO = d->m_bJScriptForce;
1317 bool bJSOO = d->m_bJScriptOverride;
1318 d->m_bJScriptForce = false;
1319 d->m_bJScriptOverride = true;
1321 QString errText = QString::fromLatin1( "<HTML><HEAD><TITLE>" );
1322 errText += i18n( "Error while loading %1" ).arg( reqUrl.htmlURL() );
1323 errText += QString::fromLatin1( "</TITLE></HEAD><BODY><P>" );
1324 errText += i18n( "An error occured while loading <B>%1</B>:" ).arg( reqUrl.htmlURL() );
1325 errText += QString::fromLatin1( "</P><P>" );
1326 QString kioErrString = KIO::buildErrorString( errorCode, text );
1328 kioErrString.replace(QRegExp("&"), QString("&"));
1329 kioErrString.replace(QRegExp("<"), QString("<"));
1330 kioErrString.replace(QRegExp(">"), QString(">"));
1332 // In case the error string has '\n' in it, replace with <BR/>
1333 kioErrString.replace( QRegExp("\n"), "<BR/>" );
1335 errText += kioErrString;
1336 errText += QString::fromLatin1( "</P></BODY></HTML>" );
1340 d->m_bJScriptForce = bJSFO;
1341 d->m_bJScriptOverride = bJSOO;
1343 // make the working url the current url, so that reload works and
1344 // emit the progress signals to advance one step in the history
1345 // (so that 'back' works)
1346 m_url = reqUrl; // same as d->m_workingURL
1347 d->m_workingURL = KURL();
1351 // following disabled until 3.1
1353 QString errorName, techName, description;
1354 QStringList causes, solutions;
1356 QByteArray raw = KIO::rawErrorDetail( errorCode, text, &reqUrl );
1357 QDataStream stream(raw, IO_ReadOnly);
1359 stream >> errorName >> techName >> description >> causes >> solutions;
1361 QString url, protocol, datetime;
1362 url = reqUrl.prettyURL();
1363 protocol = reqUrl.protocol();
1364 datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(),
1367 QString doc = QString::fromLatin1( "<html><head><title>" );
1368 doc += i18n( "Error: " );
1370 doc += QString::fromLatin1( " - %1</title></head><body><h1>" ).arg( url );
1371 doc += i18n( "The requested operation could not be completed" );
1372 doc += QString::fromLatin1( "</h1><h2>" );
1374 doc += QString::fromLatin1( "</h2>" );
1375 if ( techName != QString::null ) {
1376 doc += QString::fromLatin1( "<h2>" );
1377 doc += i18n( "Technical Reason: " );
1379 doc += QString::fromLatin1( "</h2>" );
1381 doc += QString::fromLatin1( "<h3>" );
1382 doc += i18n( "Details of the Request:" );
1383 doc += QString::fromLatin1( "</h3><ul><li>" );
1384 doc += i18n( "URL: %1" ).arg( url );
1385 doc += QString::fromLatin1( "</li><li>" );
1386 if ( protocol != QString::null ) {
1387 // uncomment for 3.1... i18n change
1388 // doc += i18n( "Protocol: %1" ).arg( protocol ).arg( protocol );
1389 doc += QString::fromLatin1( "</li><li>" );
1391 doc += i18n( "Date and Time: %1" ).arg( datetime );
1392 doc += QString::fromLatin1( "</li><li>" );
1393 doc += i18n( "Additional Information: %1" ).arg( text );
1394 doc += QString::fromLatin1( "</li></ul><h3>" );
1395 doc += i18n( "Description:" );
1396 doc += QString::fromLatin1( "</h3><p>" );
1398 doc += QString::fromLatin1( "</p>" );
1399 if ( causes.count() ) {
1400 doc += QString::fromLatin1( "<h3>" );
1401 doc += i18n( "Possible Causes:" );
1402 doc += QString::fromLatin1( "</h3><ul><li>" );
1403 doc += causes.join( "</li><li>" );
1404 doc += QString::fromLatin1( "</li></ul>" );
1406 if ( solutions.count() ) {
1407 doc += QString::fromLatin1( "<h3>" );
1408 doc += i18n( "Possible Solutions:" );
1409 doc += QString::fromLatin1( "</h3><ul><li>" );
1410 doc += solutions.join( "</li><li>" );
1411 doc += QString::fromLatin1( "</li></ul>" );
1413 doc += QString::fromLatin1( "</body></html>" );
1421 void KHTMLPart::slotFinished( KIO::Job * job )
1425 KHTMLPageCache::self()->cancelEntry(d->m_cacheId);
1428 emit canceled( job->errorString() );
1430 // TODO: what else ?
1437 //kdDebug( 6050 ) << "slotFinished" << endl;
1439 KHTMLPageCache::self()->endData(d->m_cacheId);
1441 if ( d->m_doc && d->m_doc->docLoader()->expireDate() && m_url.protocol().lower().startsWith("http"))
1442 KIO::http_update_cache(m_url, false, d->m_doc->docLoader()->expireDate());
1444 d->m_workingURL = KURL();
1447 if (d->m_doc->parsing())
1448 end(); //will emit completed()
1452 void KHTMLPart::childBegin()
1454 // We need to do this when the child is created so as to avoid the bogus state of the parent's
1455 // child->m_bCompleted being false but the child's m_bComplete being true. If the child gets
1456 // an error early on, we had trouble where checkingComplete on the child was a NOP because
1457 // it thought it was already complete, and thus the parent was never signaled, and never set
1458 // its child->m_bComplete.
1459 d->m_bComplete = false;
1463 void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
1466 // If we aren't loading an actual URL, then we need to make sure
1467 // that we have at least an empty document. createEmptyDocument will
1468 // do that if we don't have a document already.
1469 if (d->m_workingURL.isEmpty()) {
1470 KWQ(this)->createEmptyDocument();
1477 KWQ(this)->partClearedInBegin();
1480 // Only do this after clearing the part, so that JavaScript can
1481 // clean up properly if it was on for the last load.
1483 d->m_bJScriptEnabled = KHTMLFactory::defaultHTMLSettings()->isJavaScriptEnabled(url.host());
1485 d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(url.host());
1488 d->m_bCleared = false;
1490 d->m_bComplete = false;
1491 d->m_bLoadEventEmitted = false;
1492 d->m_bLoadingMainResource = true;
1496 KHTMLFactory::vLinks()->insert( KWQ(this)->requestedURLString() );
1498 QString urlString = url.url();
1499 KHTMLFactory::vLinks()->insert( urlString );
1500 QString urlString2 = url.prettyURL();
1501 if ( urlString != urlString2 ) {
1502 KHTMLFactory::vLinks()->insert( urlString2 );
1510 KParts::URLArgs args( d->m_extension->urlArgs() );
1511 args.xOffset = xOffset;
1512 args.yOffset = yOffset;
1513 d->m_extension->setURLArgs( args );
1516 ref.setUser(QSTRING_NULL);
1517 ref.setPass(QSTRING_NULL);
1518 ref.setRef(QSTRING_NULL);
1519 d->m_referrer = ref.url();
1524 // We don't need KDE chained URI handling or window caption setting
1525 if ( !m_url.isEmpty() )
1530 if ( !m_url.isEmpty() )
1532 KURL::List lst = KURL::split( m_url );
1533 if ( !lst.isEmpty() )
1534 baseurl = *lst.begin();
1536 KURL title( baseurl );
1537 title.setRef( QString::null );
1538 title.setQuery( QString::null );
1539 emit setWindowCaption( title.url() );
1542 emit setWindowCaption( i18n( "no title", "* Unknown *" ) );
1545 if (args.serviceType == "text/xml" || args.serviceType == "application/xml" || args.serviceType == "application/xhtml+xml" ||
1546 args.serviceType == "text/xsl" || args.serviceType == "application/rss+xml" || args.serviceType == "application/atom+xml")
1547 d->m_doc = DOMImplementationImpl::instance()->createDocument( d->m_view );
1549 d->m_doc = DOMImplementationImpl::instance()->createHTMLDocument( d->m_view );
1552 if (!d->m_doc->attached())
1553 d->m_doc->attach( );
1554 d->m_doc->setURL( m_url.url() );
1555 // We prefer m_baseURL over m_url because m_url changes when we are
1556 // about to load a new page.
1557 d->m_doc->setBaseURL( baseurl.url() );
1560 d->m_doc->setDecoder(d->m_decoder);
1563 d->m_doc->docLoader()->setShowAnimations( KHTMLFactory::defaultHTMLSettings()->showAnimations() );
1565 d->m_doc->docLoader()->setShowAnimations( d->m_settings->showAnimations() );
1569 KWQ(this)->updatePolicyBaseURL();
1573 d->m_paUseStylesheet->setItems(QStringList());
1574 d->m_paUseStylesheet->setEnabled( false );
1578 setAutoloadImages( KHTMLFactory::defaultHTMLSettings()->autoLoadImages() );
1579 QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
1581 setAutoloadImages( d->m_settings->autoLoadImages() );
1582 QString userStyleSheet = d->m_settings->userStyleSheet();
1585 if ( !userStyleSheet.isEmpty() )
1586 setUserStyleSheet( KURL( userStyleSheet ) );
1589 KWQ(this)->restoreDocumentState();
1591 d->m_doc->setRestoreState(args.docState);
1594 d->m_doc->implicitOpen();
1597 d->m_view->resizeContents( 0, 0 );
1598 connect(d->m_doc,SIGNAL(finishedParsing()),this,SLOT(slotFinishedParsing()));
1601 emit d->m_extension->enableAction( "print", true );
1605 void KHTMLPart::write( const char *str, int len )
1607 if ( !d->m_decoder ) {
1608 d->m_decoder = new Decoder;
1609 if (!d->m_encoding.isNull())
1610 d->m_decoder->setEncoding(d->m_encoding.latin1(),
1611 d->m_haveEncoding ? Decoder::UserChosenEncoding : Decoder::EncodingFromHTTPHeader);
1613 // Inherit the default encoding from the parent frame if there is one.
1614 const char *defaultEncoding = (parentPart() && parentPart()->d->m_decoder)
1615 ? parentPart()->d->m_decoder->encoding() : settings()->encoding().latin1();
1616 d->m_decoder->setEncoding(defaultEncoding, Decoder::DefaultEncoding);
1620 d->m_doc->setDecoder(d->m_decoder);
1627 len = strlen( str );
1629 QString decoded = d->m_decoder->decode( str, len );
1631 if(decoded.isEmpty()) return;
1633 if(d->m_bFirstData) {
1634 // determine the parse mode
1635 d->m_doc->determineParseMode( decoded );
1636 d->m_bFirstData = false;
1638 //kdDebug(6050) << "KHTMLPart::write haveEnc = " << d->m_haveEncoding << endl;
1639 // ### this is still quite hacky, but should work a lot better than the old solution
1640 if(d->m_decoder->visuallyOrdered()) d->m_doc->setVisuallyOrdered();
1641 d->m_doc->recalcStyle( NodeImpl::Force );
1645 jScript()->appendSourceFile(m_url.url(),decoded);
1646 Tokenizer* t = d->m_doc->tokenizer();
1649 t->write( decoded, true );
1652 void KHTMLPart::write( const QString &str )
1657 if(d->m_bFirstData) {
1658 // determine the parse mode
1659 d->m_doc->setParseMode( DocumentImpl::Strict );
1660 d->m_bFirstData = false;
1663 jScript()->appendSourceFile(m_url.url(),str);
1664 Tokenizer* t = d->m_doc->tokenizer();
1666 t->write( str, true );
1669 void KHTMLPart::end()
1671 d->m_bLoadingMainResource = false;
1675 void KHTMLPart::endIfNotLoading()
1677 if (d->m_bLoadingMainResource)
1680 // make sure nothing's left in there...
1682 write(d->m_decoder->flush());
1684 d->m_doc->finishParsing();
1686 // WebKit partially uses WebCore when loading non-HTML docs. In these cases doc==nil, but
1687 // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
1688 // become true. An example is when a subframe is a pure text doc, and that subframe is the
1689 // last one to complete.
1693 void KHTMLPart::stop()
1695 // make sure nothing's left in there...
1696 Tokenizer* t = d->m_doc ? d->m_doc->tokenizer() : 0;
1700 d->m_doc->finishParsing();
1702 // WebKit partially uses WebCore when loading non-HTML docs. In these cases doc==nil, but
1703 // WebCore is enough involved that we need to checkCompleted() in order for m_bComplete to
1704 // become true. An example is when a subframe is a pure text doc, and that subframe is the
1705 // last one to complete.
1711 void KHTMLPart::paint(QPainter *p, const QRect &rc, int yOff, bool *more)
1713 if (!d->m_view) return;
1714 d->m_view->paint(p, rc, yOff, more);
1719 void KHTMLPart::stopAnimations()
1722 d->m_doc->docLoader()->setShowAnimations( KHTMLSettings::KAnimationDisabled );
1724 ConstFrameIt it = d->m_frames.begin();
1725 ConstFrameIt end = d->m_frames.end();
1726 for (; it != end; ++it )
1727 if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
1728 KParts::ReadOnlyPart* p = ( *it ).m_part;
1729 static_cast<KHTMLPart*>( p )->stopAnimations();
1733 void KHTMLPart::gotoAnchor()
1735 if (m_url.hasRef()) {
1736 QString ref = m_url.encodedHtmlRef();
1737 if (!gotoAnchor(ref)) {
1738 // Can't use htmlRef() here because it doesn't know which encoding to use to decode.
1739 // Decoding here has to match encoding in completeURL, which means it has to use the
1740 // page's encoding rather than UTF-8.
1743 gotoAnchor(KURL::decode_string(ref, d->m_decoder->codec()->mibEnum()));
1745 gotoAnchor(KURL::decode_string(ref, d->m_decoder->codec()));
1751 void KHTMLPart::slotFinishedParsing()
1753 d->m_doc->setParsing(false);
1756 return; // We are probably being destructed.
1761 return; // We are being destroyed by something checkCompleted called.
1763 // check if the scrollbars are really needed for the content
1764 // if not, remove them, relayout, and repaint
1766 d->m_view->restoreScrollBar();
1770 void KHTMLPart::slotLoaderRequestStarted( khtml::DocLoader* dl, khtml::CachedObject *obj )
1773 if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
1774 KHTMLPart* p = this;
1777 p->d->m_totalObjectCount++;
1778 p = p->parentPart();
1779 if ( !p && d->m_loadedObjects <= d->m_totalObjectCount )
1780 QTimer::singleShot( 200, op, SLOT( slotProgressUpdate() ) );
1786 void KHTMLPart::slotLoaderRequestDone( khtml::DocLoader* dl, khtml::CachedObject *obj )
1789 if ( obj && obj->type() == khtml::CachedObject::Image && d->m_doc && d->m_doc->docLoader() == dl ) {
1790 KHTMLPart* p = this;
1793 p->d->m_loadedObjects++;
1794 p = p->parentPart();
1795 if ( !p && d->m_loadedObjects <= d->m_totalObjectCount && d->m_jobPercent >= 100 )
1796 QTimer::singleShot( 200, op, SLOT( slotProgressUpdate() ) );
1800 // We really only need to call checkCompleted when our own resources are done loading.
1801 // So we should check that d->m_doc->docLoader() == dl here.
1802 // That might help with performance by skipping some unnecessary work, but it's too
1803 // risky to make that change right now (2005-02-07), because we might be accidentally
1804 // depending on the extra checkCompleted calls.
1812 void KHTMLPart::slotProgressUpdate()
1815 if ( d->m_loadedObjects < d->m_totalObjectCount )
1816 percent = d->m_jobPercent / 4 + ( d->m_loadedObjects*300 ) / ( 4*d->m_totalObjectCount );
1818 percent = d->m_jobPercent;
1820 if ( d->m_loadedObjects < d->m_totalObjectCount && percent >= 75 )
1821 emit d->m_extension->infoMessage( i18n( "%1 of 1 Image loaded", "%1 of %n Images loaded", d->m_totalObjectCount ).arg( d->m_loadedObjects ) );
1823 emit d->m_extension->loadingProgress( percent );
1826 void KHTMLPart::slotJobSpeed( KIO::Job* /*job*/, unsigned long speed )
1828 emit d->m_extension->speedProgress( speed );
1831 void KHTMLPart::slotJobPercent( KIO::Job* /*job*/, unsigned long percent )
1833 d->m_jobPercent = percent;
1835 if ( !parentPart() )
1836 QTimer::singleShot( 0, this, SLOT( slotProgressUpdate() ) );
1841 void KHTMLPart::checkCompleted()
1843 // kdDebug( 6050 ) << "KHTMLPart::checkCompleted() parsing: " << d->m_doc->parsing() << endl;
1844 // kdDebug( 6050 ) << " complete: " << d->m_bComplete << endl;
1847 // restore the cursor position
1848 if (d->m_doc && !d->m_doc->parsing() && !d->m_focusNodeRestored)
1850 if (d->m_focusNodeNumber >= 0)
1851 d->m_doc->setFocusNode(d->m_doc->nodeWithAbsIndex(d->m_focusNodeNumber));
1853 d->m_doc->setFocusNode(0);
1854 d->m_focusNodeRestored = true;
1858 // Any frame that hasn't completed yet ?
1859 ConstFrameIt it = d->m_frames.begin();
1860 ConstFrameIt end = d->m_frames.end();
1861 for (; it != end; ++it )
1862 if ( !(*it).m_bCompleted )
1865 // Have we completed before?
1866 if ( d->m_bComplete )
1869 // Are we still parsing?
1870 if ( d->m_doc && d->m_doc->parsing() )
1873 // Still waiting for images/scripts from the loader ?
1875 if ( d->m_doc && d->m_doc->docLoader() )
1876 requests = khtml::Cache::loader()->numRequests( d->m_doc->docLoader() );
1882 // Now do what should be done when we are really completed.
1883 d->m_bComplete = true;
1885 checkEmitLoadEvent(); // if we didn't do it before
1888 // check that the view has not been moved by the user
1889 if ( !m_url.hasRef() && d->m_view->contentsY() == 0 )
1890 d->m_view->setContentsPos( d->m_extension->urlArgs().xOffset,
1891 d->m_extension->urlArgs().yOffset );
1894 if ( d->m_scheduledRedirection != noRedirectionScheduled )
1896 // Do not start redirection for frames here! That action is
1897 // deferred until the parent emits a completed signal.
1898 if ( parentPart() == 0 )
1899 d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
1901 emit completed( true );
1905 if ( d->m_bPendingChildRedirection )
1906 emit completed ( true );
1912 // find the alternate stylesheets
1915 sheets = d->m_doc->availableStyleSheets();
1916 d->m_paUseStylesheet->setItems( sheets );
1917 d->m_paUseStylesheet->setEnabled( !sheets.isEmpty() );
1918 if (!sheets.isEmpty())
1920 d->m_paUseStylesheet->setCurrentItem(kMax(sheets.findIndex(d->m_sheetUsed), 0));
1921 slotUseStylesheet();
1925 emit setStatusBarText(i18n("Done."));
1929 kdDebug(6050) << "DONE: " <<d->m_parsetime.elapsed() << endl;
1933 void KHTMLPart::checkEmitLoadEvent()
1935 if ( d->m_bLoadEventEmitted || !d->m_doc || d->m_doc->parsing() ) return;
1937 ConstFrameIt it = d->m_frames.begin();
1938 ConstFrameIt end = d->m_frames.end();
1939 for (; it != end; ++it )
1940 if ( !(*it).m_bCompleted ) // still got a frame running -> too early
1944 // All frames completed -> set their domain to the frameset's domain
1945 // This must only be done when loading the frameset initially (#22039),
1946 // not when following a link in a frame (#44162).
1949 DOMString domain = d->m_doc->domain();
1950 ConstFrameIt it = d->m_frames.begin();
1951 ConstFrameIt end = d->m_frames.end();
1952 for (; it != end; ++it )
1954 KParts::ReadOnlyPart *p = (*it).m_part;
1955 if ( p && p->inherits( "KHTMLPart" ))
1957 KHTMLPart* htmlFrame = static_cast<KHTMLPart *>(p);
1958 if (htmlFrame->d->m_doc)
1960 kdDebug() << "KHTMLPart::checkCompleted setting frame domain to " << domain.string() << endl;
1961 htmlFrame->d->m_doc->setDomain( domain );
1967 d->m_bLoadEventEmitted = true;
1968 d->m_bUnloadEventEmitted = false;
1970 d->m_doc->implicitClose();
1973 const KHTMLSettings *KHTMLPart::settings() const
1975 return d->m_settings;
1978 #ifndef KDE_NO_COMPAT
1979 KURL KHTMLPart::baseURL() const
1981 if ( !d->m_doc ) return KURL();
1983 return d->m_doc->baseURL();
1986 QString KHTMLPart::baseTarget() const
1988 if ( !d->m_doc ) return QString::null;
1990 return d->m_doc->baseTarget();
1994 KURL KHTMLPart::completeURL( const QString &url )
1996 if ( !d->m_doc ) return url;
2000 return KURL(d->m_doc->completeURL(url), d->m_decoder->codec()->mibEnum());
2003 return KURL( d->m_doc->completeURL( url ) );
2006 void KHTMLPart::scheduleRedirection( double delay, const QString &url, bool doLockHistory)
2008 kdDebug(6050) << "KHTMLPart::scheduleRedirection delay=" << delay << " url=" << url << endl;
2009 if (delay < 0 || delay > INT_MAX / 1000)
2011 if ( d->m_scheduledRedirection == noRedirectionScheduled || delay <= d->m_delayRedirect )
2013 d->m_scheduledRedirection = redirectionScheduled;
2014 d->m_delayRedirect = delay;
2015 d->m_redirectURL = url;
2016 d->m_redirectReferrer = QString::null;
2017 d->m_redirectLockHistory = doLockHistory;
2018 d->m_redirectUserGesture = false;
2020 d->m_redirectionTimer.stop();
2021 if ( d->m_bComplete )
2022 d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
2026 void KHTMLPart::scheduleLocationChange(const QString &url, const QString &referrer, bool lockHistory, bool userGesture)
2028 // Handle a location change of a page with no document as a special case.
2029 // This may happen when a frame changes the location of another frame.
2030 d->m_scheduledRedirection = d->m_doc ? locationChangeScheduled : locationChangeScheduledDuringLoad;
2031 d->m_delayRedirect = 0;
2032 d->m_redirectURL = url;
2033 d->m_redirectReferrer = referrer;
2034 d->m_redirectLockHistory = lockHistory;
2035 d->m_redirectUserGesture = userGesture;
2036 d->m_redirectionTimer.stop();
2038 d->m_redirectionTimer.start(0, true);
2041 bool KHTMLPart::isScheduledLocationChangePending() const
2043 switch (d->m_scheduledRedirection) {
2044 case noRedirectionScheduled:
2045 case redirectionScheduled:
2047 case historyNavigationScheduled:
2048 case locationChangeScheduled:
2049 case locationChangeScheduledDuringLoad:
2055 void KHTMLPart::scheduleHistoryNavigation( int steps )
2058 // navigation will always be allowed in the 0 steps case, which is OK because
2059 // that's supposed to force a reload.
2060 if (!KWQ(this)->canGoBackOrForward(steps)) {
2061 cancelRedirection();
2066 d->m_scheduledRedirection = historyNavigationScheduled;
2067 d->m_delayRedirect = 0;
2068 d->m_redirectURL = QString::null;
2069 d->m_redirectReferrer = QString::null;
2070 d->m_scheduledHistoryNavigationSteps = steps;
2071 d->m_redirectionTimer.stop();
2073 d->m_redirectionTimer.start(0, true);
2076 void KHTMLPart::cancelRedirection(bool cancelWithLoadInProgress)
2079 d->m_cancelWithLoadInProgress = cancelWithLoadInProgress;
2080 d->m_scheduledRedirection = noRedirectionScheduled;
2081 d->m_redirectionTimer.stop();
2085 void KHTMLPart::slotRedirect()
2087 if (d->m_scheduledRedirection == historyNavigationScheduled) {
2088 d->m_scheduledRedirection = noRedirectionScheduled;
2090 // Special case for go(0) from a frame -> reload only the frame
2091 // go(i!=0) from a frame navigates into the history of the frame only,
2092 // in both IE and NS (but not in Mozilla).... we can't easily do that
2094 if (d->m_scheduledHistoryNavigationSteps == 0) // add && parentPart() to get only frames, but doesn't matter
2095 openURL( url() ); /// ## need args.reload=true?
2097 if (d->m_extension) {
2098 BrowserInterface *interface = d->m_extension->browserInterface();
2100 interface->callMethod( "goHistory(int)", d->m_scheduledHistoryNavigationSteps );
2106 QString u = d->m_redirectURL;
2108 d->m_scheduledRedirection = noRedirectionScheduled;
2109 d->m_delayRedirect = 0;
2110 d->m_redirectURL = QString::null;
2111 if ( u.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2113 QString script = KURL::decode_string( u.right( u.length() - 11 ) );
2114 //kdDebug( 6050 ) << "KHTMLPart::slotRedirect script=" << script << endl;
2115 QVariant res = executeScript( script, d->m_redirectUserGesture );
2116 if ( res.type() == QVariant::String ) {
2118 write( res.asString() );
2123 KParts::URLArgs args;
2124 if ( urlcmp( u, m_url.url(), true, false ) )
2127 args.setLockHistory( d->m_redirectLockHistory );
2128 if (!d->m_redirectReferrer.isEmpty())
2129 args.metaData()["referrer"] = d->m_redirectReferrer;
2130 d->m_redirectReferrer = QString::null;
2132 urlSelected( u, 0, 0, "_self", args );
2135 void KHTMLPart::slotRedirection(KIO::Job*, const KURL& url)
2137 // the slave told us that we got redirected
2138 // kdDebug( 6050 ) << "redirection by KIO to " << url.url() << endl;
2139 emit d->m_extension->setLocationBarURL( url.prettyURL() );
2140 d->m_workingURL = url;
2145 bool KHTMLPart::setEncoding( const QString &name, bool override )
2147 d->m_encoding = name;
2148 d->m_haveEncoding = override;
2150 if( !m_url.isEmpty() ) {
2155 d->m_restored = true;
2157 d->m_restored = false;
2165 QString KHTMLPart::encoding() const
2167 if(d->m_haveEncoding && !d->m_encoding.isEmpty())
2168 return d->m_encoding;
2170 if(d->m_decoder && d->m_decoder->encoding())
2171 return QString(d->m_decoder->encoding());
2173 return(settings()->encoding());
2176 void KHTMLPart::setUserStyleSheet(const KURL &url)
2178 if ( d->m_doc && d->m_doc->docLoader() )
2179 (void) new khtml::PartStyleSheetLoader(this, url.url(), d->m_doc->docLoader());
2182 void KHTMLPart::setUserStyleSheet(const QString &styleSheet)
2185 d->m_doc->setUserStyleSheet( styleSheet );
2188 bool KHTMLPart::gotoAnchor( const QString &name )
2193 NodeImpl *n = d->m_doc->getElementById(name);
2195 HTMLCollectionImpl *anchors =
2196 new HTMLCollectionImpl( d->m_doc, HTMLCollectionImpl::DOC_ANCHORS);
2198 n = anchors->namedItem(name, !d->m_doc->inCompatMode());
2202 d->m_doc->setCSSTarget(n); // Setting to null will clear the current target.
2204 // Implement the rule that "" and "top" both mean top of page as in other browsers.
2205 if (!n && !(name.isEmpty() || name.lower() == "top")) {
2206 kdDebug(6050) << "KHTMLPart::gotoAnchor node '" << name << "' not found" << endl;
2210 // We need to update the layout before scrolling, otherwise we could
2211 // really mess things up if an anchor scroll comes at a bad moment.
2213 d->m_doc->updateRendering();
2214 // Only do a layout if changes have occurred that make it necessary.
2215 if ( d->m_view && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout() ) {
2216 d->m_view->layout();
2222 static_cast<HTMLElementImpl *>(n)->getUpperLeftCorner(x, y);
2224 // Scroll to actual top left of element with no slop, since some pages expect anchors to be exactly scrolled to.
2226 // Call recursive version so this will expose correctly from within nested frames.
2227 d->m_view->setContentsPosRecursive(x, y);
2229 d->m_view->setContentsPos(x, y);
2235 void KHTMLPart::setStandardFont( const QString &name )
2237 d->m_settings->setStdFontName(name);
2240 void KHTMLPart::setFixedFont( const QString &name )
2242 d->m_settings->setFixedFontName(name);
2247 void KHTMLPart::setURLCursor( const QCursor &c )
2249 d->m_linkCursor = c;
2254 QCursor KHTMLPart::urlCursor() const
2257 // Don't load the link cursor until it's actually used.
2258 // Also, we don't need setURLCursor.
2259 // This speeds up startup time.
2260 return KCursor::handCursor();
2262 return d->m_linkCursor;
2266 bool KHTMLPart::onlyLocalReferences() const
2268 return d->m_onlyLocalReferences;
2271 void KHTMLPart::setOnlyLocalReferences(bool enable)
2273 d->m_onlyLocalReferences = enable;
2278 void KHTMLPart::findTextBegin(NodeImpl *startNode, int startPos)
2280 d->m_findPos = startPos;
2281 d->m_findNode = startNode;
2284 bool KHTMLPart::findTextNext( const QString &str, bool forward, bool caseSensitive, bool isRegExp )
2289 if(!d->m_findNode) {
2290 if (d->m_doc->isHTMLDocument())
2291 d->m_findNode = static_cast<HTMLDocumentImpl*>(d->m_doc)->body();
2293 d->m_findNode = d->m_doc;
2296 if ( !d->m_findNode )
2298 kdDebug() << "KHTMLPart::findTextNext no findNode -> return false" << endl;
2301 if ( d->m_findNode->id() == ID_FRAMESET )
2303 kdDebug() << "KHTMLPart::findTextNext FRAMESET -> return false" << endl;
2309 if( (d->m_findNode->nodeType() == Node::TEXT_NODE || d->m_findNode->nodeType() == Node::CDATA_SECTION_NODE) && d->m_findNode->renderer() )
2311 DOMString nodeText = d->m_findNode->nodeValue();
2312 DOMStringImpl *t = nodeText.implementation();
2313 QConstString s(t->s, t->l);
2317 QRegExp matcher( str );
2318 matcher.setCaseSensitive( caseSensitive );
2319 d->m_findPos = matcher.search(s.string(), d->m_findPos+1);
2320 if ( d->m_findPos != -1 )
2321 matchLen = matcher.matchedLength();
2324 d->m_findPos = s.string().find(str, d->m_findPos+1, caseSensitive);
2325 matchLen = str.length();
2328 if(d->m_findPos != -1)
2331 static_cast<khtml::RenderText *>(d->m_findNode->renderer())
2332 ->posOfChar(d->m_findPos, x, y);
2333 d->m_view->setContentsPos(x-50, y-50);
2334 Position p1(d->m_findNode, d->m_findPos);
2335 Position p2(d->m_findNode, d->m_findPos + matchLen);
2336 setSelection(Selection(p1, khtml::DOWNSTREAM, p2, khtml::SEL_PREFER_UPSTREAM_AFFINITY));
2346 next = d->m_findNode->firstChild();
2348 if(!next) next = d->m_findNode->nextSibling();
2349 while(d->m_findNode && !next) {
2350 d->m_findNode = d->m_findNode->parentNode();
2351 if( d->m_findNode ) {
2352 next = d->m_findNode->nextSibling();
2358 next = d->m_findNode->lastChild();
2360 if (!next ) next = d->m_findNode->previousSibling();
2361 while ( d->m_findNode && !next )
2363 d->m_findNode = d->m_findNode->parentNode();
2366 next = d->m_findNode->previousSibling();
2371 d->m_findNode = next;
2372 if(!d->m_findNode) return false;
2376 #endif // APPLE_CHANGES
2378 QString KHTMLPart::text(const DOM::Range &r) const
2380 return plainText(r);
2383 QString KHTMLPart::selectedText() const
2385 return text(selection().toRange());
2388 bool KHTMLPart::hasSelection() const
2390 return d->m_selection.isCaretOrRange();
2393 const Selection &KHTMLPart::selection() const
2395 return d->m_selection;
2398 ETextGranularity KHTMLPart::selectionGranularity() const
2400 return d->m_selectionGranularity;
2403 void KHTMLPart::setSelectionGranularity(ETextGranularity granularity) const
2405 d->m_selectionGranularity = granularity;
2408 const Selection &KHTMLPart::dragCaret() const
2410 return d->m_dragCaret;
2413 const Selection &KHTMLPart::mark() const
2418 void KHTMLPart::setMark(const Selection &s)
2423 void KHTMLPart::setSelection(const Selection &s, bool closeTyping, bool keepTypingStyle)
2425 if (d->m_selection == s) {
2429 clearCaretRectIfNeeded();
2432 Selection oldSelection = d->m_selection;
2437 setFocusNodeIfNeeded();
2439 selectionLayoutChanged();
2441 // Always clear the x position used for vertical arrow navigation.
2442 // It will be restored by the vertical arrow navigation code if necessary.
2443 d->m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation;
2446 TypingCommand::closeTyping(lastEditCommand());
2448 if (!keepTypingStyle)
2452 KWQ(this)->respondToChangedSelection(oldSelection, closeTyping);
2455 emitSelectionChanged();
2458 void KHTMLPart::setDragCaret(const Selection &dragCaret)
2460 if (d->m_dragCaret != dragCaret) {
2461 d->m_dragCaret.needsCaretRepaint();
2462 d->m_dragCaret = dragCaret;
2463 d->m_dragCaret.needsCaretRepaint();
2467 void KHTMLPart::clearSelection()
2469 setSelection(Selection());
2472 void KHTMLPart::invalidateSelection()
2474 clearCaretRectIfNeeded();
2475 d->m_selection.setNeedsLayout();
2476 selectionLayoutChanged();
2479 void KHTMLPart::setCaretVisible(bool flag)
2481 if (d->m_caretVisible == flag)
2483 clearCaretRectIfNeeded();
2485 setFocusNodeIfNeeded();
2486 d->m_caretVisible = flag;
2487 selectionLayoutChanged();
2491 void KHTMLPart::slotClearSelection()
2497 void KHTMLPart::clearCaretRectIfNeeded()
2499 if (d->m_caretPaint) {
2500 d->m_caretPaint = false;
2501 d->m_selection.needsCaretRepaint();
2505 // Helper function that tells whether a particular node is an element that has an entire
2506 // KHTMLPart and KHTMLView, a <frame>, <iframe>, or <object>.
2507 static bool isFrame(const NodeImpl *n)
2511 RenderObject *renderer = n->renderer();
2512 if (!renderer || !renderer->isWidget())
2514 QWidget *widget = static_cast<RenderWidget *>(renderer)->widget();
2515 return widget && widget->inherits("KHTMLView");
2518 void KHTMLPart::setFocusNodeIfNeeded()
2520 if (!xmlDocImpl() || d->m_selection.isNone() || !d->m_isFocused)
2523 NodeImpl *n = d->m_selection.start().node();
2524 NodeImpl *target = (n && n->isContentEditable()) ? n : 0;
2526 while (n && n != d->m_selection.end().node()) {
2527 if (n->isContentEditable()) {
2531 n = n->traverseNextNode();
2534 assert(target == 0 || target->isContentEditable());
2537 for ( ; target; target = target->parentNode()) {
2538 // We don't want to set focus on a subframe when selecting in a parent frame,
2539 // so add the !isFrame check here. There's probably a better way to make this
2540 // work in the long term, but this is the safest fix at this time.
2541 if (target->isMouseFocusable() && !isFrame(target)) {
2542 xmlDocImpl()->setFocusNode(target);
2546 xmlDocImpl()->setFocusNode(0);
2550 void KHTMLPart::selectionLayoutChanged()
2552 // kill any caret blink timer now running
2553 if (d->m_caretBlinkTimer >= 0) {
2554 killTimer(d->m_caretBlinkTimer);
2555 d->m_caretBlinkTimer = -1;
2558 // see if a new caret blink timer needs to be started
2559 if (d->m_caretVisible && d->m_caretBlinks &&
2560 d->m_selection.isCaret() && d->m_selection.start().node()->isContentEditable()) {
2561 d->m_caretBlinkTimer = startTimer(CARET_BLINK_FREQUENCY);
2562 d->m_caretPaint = true;
2563 d->m_selection.needsCaretRepaint();
2567 d->m_doc->updateSelection();
2570 void KHTMLPart::setXPosForVerticalArrowNavigation(int x)
2572 d->m_xPosForVerticalArrowNavigation = x;
2575 int KHTMLPart::xPosForVerticalArrowNavigation() const
2577 return d->m_xPosForVerticalArrowNavigation;
2580 void KHTMLPart::timerEvent(QTimerEvent *e)
2582 if (e->timerId() == d->m_caretBlinkTimer &&
2583 d->m_caretVisible &&
2585 d->m_selection.isCaret()) {
2586 if (d->m_bMousePressed) {
2587 if (!d->m_caretPaint) {
2588 d->m_caretPaint = true;
2589 d->m_selection.needsCaretRepaint();
2593 d->m_caretPaint = !d->m_caretPaint;
2594 d->m_selection.needsCaretRepaint();
2599 void KHTMLPart::paintCaret(QPainter *p, const QRect &rect) const
2601 if (d->m_caretPaint)
2602 d->m_selection.paintCaret(p, rect);
2605 void KHTMLPart::paintDragCaret(QPainter *p, const QRect &rect) const
2607 d->m_dragCaret.paintCaret(p, rect);
2612 void KHTMLPart::overURL( const QString &url, const QString &target, bool shiftPressed )
2614 if ( !d->m_kjsStatusBarText.isEmpty() && !shiftPressed ) {
2616 emit setStatusBarText( d->m_kjsStatusBarText );
2617 d->m_kjsStatusBarText = QString::null;
2623 if ( url.isEmpty() )
2625 emit setStatusBarText(completeURL(url).htmlURL());
2629 if (url.find( QString::fromLatin1( "javascript:" ),0, false ) != -1 )
2631 emit setStatusBarText( KURL::decode_string( url.mid( url.find( "javascript:", 0, false ) ) ) );
2635 KURL u = completeURL(url);
2637 // special case for <a href="">
2638 if ( url.isEmpty() )
2639 u.setFileName( url );
2643 KMimeType::Ptr typ = KMimeType::findByURL( u );
2646 com = typ->comment( u, false );
2648 if ( u.isMalformed() )
2650 emit setStatusBarText(u.htmlURL());
2654 if ( u.isLocalFile() )
2656 // TODO : use KIO::stat() and create a KFileItem out of its result,
2657 // to use KFileItem::statusBarText()
2658 QCString path = QFile::encodeName( u.path() );
2661 bool ok = !stat( path.data(), &buff );
2664 if (ok) ok = !lstat( path.data(), &lbuff );
2666 QString text = u.htmlURL();
2667 QString text2 = text;
2669 if (ok && S_ISLNK( lbuff.st_mode ) )
2673 tmp = i18n( "Symbolic Link");
2675 tmp = i18n("%1 (Link)").arg(com);
2676 char buff_two[1024];
2678 int n = readlink ( path.data(), buff_two, 1022);
2683 emit setStatusBarText(text2);
2692 else if ( ok && S_ISREG( buff.st_mode ) )
2694 if (buff.st_size < 1024)
2695 text = i18n("%2 (%1 bytes)").arg((long) buff.st_size).arg(text2); // always put the URL last, in case it contains '%'
2698 float d = (float) buff.st_size/1024.0;
2699 text = i18n("%1 (%2 K)").arg(text2).arg(KGlobal::locale()->formatNumber(d, 2)); // was %.2f
2704 else if ( ok && S_ISDIR( buff.st_mode ) )
2714 emit setStatusBarText(text);
2719 if (target == QString::fromLatin1("_blank"))
2721 extra = i18n(" (In new window)");
2723 else if (!target.isEmpty() &&
2724 (target != QString::fromLatin1("_top")) &&
2725 (target != QString::fromLatin1("_self")) &&
2726 (target != QString::fromLatin1("_parent")))
2728 extra = i18n(" (In other frame)");
2731 if (u.protocol() == QString::fromLatin1("mailto")) {
2732 QString mailtoMsg/* = QString::fromLatin1("<img src=%1>").arg(locate("icon", QString::fromLatin1("locolor/16x16/actions/mail_send.png")))*/;
2733 mailtoMsg += i18n("Email to: ") + KURL::decode_string(u.path());
2734 QStringList queries = QStringList::split('&', u.query().mid(1));
2735 for (QStringList::Iterator it = queries.begin(); it != queries.end(); ++it)
2736 if ((*it).startsWith(QString::fromLatin1("subject=")))
2737 mailtoMsg += i18n(" - Subject: ") + KURL::decode_string((*it).mid(8));
2738 else if ((*it).startsWith(QString::fromLatin1("cc=")))
2739 mailtoMsg += i18n(" - CC: ") + KURL::decode_string((*it).mid(3));
2740 else if ((*it).startsWith(QString::fromLatin1("bcc=")))
2741 mailtoMsg += i18n(" - BCC: ") + KURL::decode_string((*it).mid(4));
2742 mailtoMsg.replace(QRegExp("&"), QString("&"));
2743 mailtoMsg.replace(QRegExp("<"), QString("<"));
2744 mailtoMsg.replace(QRegExp(">"), QString(">"));
2745 mailtoMsg.replace(QRegExp("([\n\r\t]|[ ]{10})"), "");
2746 emit setStatusBarText(mailtoMsg);
2749 // Is this check neccessary at all? (Frerich)
2751 else if (u.protocol() == QString::fromLatin1("http")) {
2752 DOM::Node hrefNode = nodeUnderMouse().parentNode();
2753 while (hrefNode.nodeName().string() != QString::fromLatin1("A") && !hrefNode.isNull())
2754 hrefNode = hrefNode.parentNode();
2756 if (!hrefNode.isNull()) {
2757 DOM::Node hreflangNode = hrefNode.attributes().getNamedItem("HREFLANG");
2758 if (!hreflangNode.isNull()) {
2759 QString countryCode = hreflangNode.nodeValue().string().lower();
2760 // Map the language code to an appropriate country code.
2761 if (countryCode == QString::fromLatin1("en"))
2762 countryCode = QString::fromLatin1("gb");
2763 QString flagImg = QString::fromLatin1("<img src=%1>").arg(
2764 locate("locale", QString::fromLatin1("l10n/")
2766 + QString::fromLatin1("/flag.png")));
2767 emit setStatusBarText(flagImg + u.prettyURL() + extra);
2772 emit setStatusBarText(u.htmlURL() + extra);
2776 #endif // APPLE_CHANGES
2778 void KHTMLPart::urlSelected( const QString &url, int button, int state, const QString &_target,
2779 KParts::URLArgs args )
2781 bool hasTarget = false;
2783 QString target = _target;
2784 if ( target.isEmpty() && d->m_doc )
2785 target = d->m_doc->baseTarget();
2786 if ( !target.isEmpty() )
2789 if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
2791 executeScript( KURL::decode_string( url.right( url.length() - 11) ), true );
2795 KURL cURL = completeURL(url);
2797 // special case for <a href="">
2798 if ( url.isEmpty() )
2799 cURL.setFileName( url );
2802 if ( !cURL.isValid() )
2803 // ### ERROR HANDLING
2806 //kdDebug( 6000 ) << "urlSelected: complete URL:" << cURL.url() << " target = " << target << endl;
2809 if ( button == LeftButton && ( state & ShiftButton ) )
2811 KIO::MetaData metaData;
2812 metaData["referrer"] = d->m_referrer;
2813 KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As..." ), cURL, metaData );
2817 if (!checkLinkSecurity(cURL,
2818 i18n( "<qt>The link <B>%1</B><BR>leads from this untrusted page to your local filesystem.<BR>Do you want to follow the link?" ),
2823 args.frameName = target;
2825 if ( d->m_bHTTPRefresh )
2827 d->m_bHTTPRefresh = false;
2828 args.metaData()["cache"] = "refresh";
2832 args.metaData().insert("main_frame_request",
2833 parentPart() == 0 ? "TRUE":"FALSE");
2834 args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
2835 args.metaData().insert("ssl_activate_warnings", "TRUE");
2839 args.metaData()["referrer"] = d->m_referrer;
2840 KWQ(this)->urlSelected(cURL, button, state, args);
2844 // unknown frame names should open in a new window.
2845 khtml::ChildFrame *frame = recursiveFrameRequest( cURL, args, false );
2848 args.metaData()["referrer"] = d->m_referrer;
2849 requestObject( frame, cURL, args );
2854 if ( !d->m_bComplete && !hasTarget )
2857 if (!d->m_referrer.isEmpty())
2858 args.metaData()["referrer"] = d->m_referrer;
2860 if ( button == MidButton && (state & ShiftButton) )
2862 KParts::WindowArgs winArgs;
2863 winArgs.lowerWindow = true;
2864 KParts::ReadOnlyPart *newPart = 0;
2865 emit d->m_extension->createNewWindow( cURL, args, winArgs, newPart );
2868 emit d->m_extension->openURLRequest( cURL, args );
2869 #endif // APPLE_CHANGES
2874 void KHTMLPart::slotViewDocumentSource()
2877 if (!(url.isLocalFile()) && KHTMLPageCache::self()->isValid(d->m_cacheId))
2879 KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
2880 if (sourceFile.status() == 0)
2882 KHTMLPageCache::self()->saveData(d->m_cacheId, sourceFile.dataStream());
2884 url.setPath(sourceFile.name());
2888 // emit d->m_extension->openURLRequest( m_url, KParts::URLArgs( false, 0, 0, QString::fromLatin1( "text/plain" ) ) );
2889 (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
2892 void KHTMLPart::slotViewFrameSource()
2894 KParts::ReadOnlyPart *frame = currentFrame();
2898 KURL url = frame->url();
2899 if (!(url.isLocalFile()) && frame->inherits("KHTMLPart"))
2901 long cacheId = static_cast<KHTMLPart *>(frame)->d->m_cacheId;
2903 if (KHTMLPageCache::self()->isValid(cacheId))
2905 KTempFile sourceFile(QString::null, QString::fromLatin1(".html"));
2906 if (sourceFile.status() == 0)
2908 KHTMLPageCache::self()->saveData(cacheId, sourceFile.dataStream());
2910 url.setPath(sourceFile.name());
2915 (void) KRun::runURL( url, QString::fromLatin1("text/plain") );
2918 KURL KHTMLPart::backgroundURL() const
2920 // ### what about XML documents? get from CSS?
2921 if (!d->m_doc || !d->m_doc->isHTMLDocument())
2924 QString relURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
2926 return KURL( m_url, relURL );
2929 void KHTMLPart::slotSaveBackground()
2931 KIO::MetaData metaData;
2932 metaData["referrer"] = d->m_referrer;
2933 KHTMLPopupGUIClient::saveURL( d->m_view, i18n("Save background image as"), backgroundURL(), metaData );
2936 void KHTMLPart::slotSaveDocument()
2938 KURL srcURL( m_url );
2940 if ( srcURL.fileName(false).isEmpty() )
2941 srcURL.setFileName( "index.html" );
2943 KIO::MetaData metaData;
2945 KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files"), d->m_cacheId );
2948 void KHTMLPart::slotSecurity()
2950 // kdDebug( 6050 ) << "Meta Data:" << endl
2951 // << d->m_ssl_peer_cert_subject
2953 // << d->m_ssl_peer_cert_issuer
2955 // << d->m_ssl_cipher
2957 // << d->m_ssl_cipher_desc
2959 // << d->m_ssl_cipher_version
2961 // << d->m_ssl_good_from
2963 // << d->m_ssl_good_until
2965 // << d->m_ssl_cert_state
2968 KSSLInfoDlg *kid = new KSSLInfoDlg(d->m_ssl_in_use, widget(), "kssl_info_dlg", true );
2970 if (d->m_bSecurityInQuestion)
2971 kid->setSecurityInQuestion(true);
2973 if (d->m_ssl_in_use) {
2974 KSSLCertificate *x = KSSLCertificate::fromString(d->m_ssl_peer_certificate.local8Bit());
2976 // Set the chain back onto the certificate
2977 QStringList cl = QStringList::split(QString("\n"), d->m_ssl_peer_chain);
2978 QPtrList<KSSLCertificate> ncl;
2980 ncl.setAutoDelete(true);
2981 for (QStringList::Iterator it = cl.begin(); it != cl.end(); ++it) {
2982 KSSLCertificate *y = KSSLCertificate::fromString((*it).local8Bit());
2983 if (y) ncl.append(y);
2986 if (ncl.count() > 0)
2987 x->chain().setChain(ncl);
2993 d->m_ssl_cipher_desc,
2994 d->m_ssl_cipher_version,
2995 d->m_ssl_cipher_used_bits.toInt(),
2996 d->m_ssl_cipher_bits.toInt(),
2997 (KSSLCertificate::KSSLValidation) d->m_ssl_cert_state.toInt()
3005 void KHTMLPart::slotSaveFrame()
3007 if ( !d->m_activeFrame )
3008 return; // should never be the case, but one never knows :-)
3010 KURL srcURL( static_cast<KParts::ReadOnlyPart *>( d->m_activeFrame )->url() );
3012 if ( srcURL.fileName(false).isEmpty() )
3013 srcURL.setFileName( "index.html" );
3015 KIO::MetaData metaData;
3016 // Referrer unknown?
3017 KHTMLPopupGUIClient::saveURL( d->m_view, i18n( "Save As" ), srcURL, metaData, i18n("*.html *.htm|HTML files") );
3020 void KHTMLPart::slotSetEncoding()
3022 // first Item is always auto
3023 if(d->m_paSetEncoding->currentItem() == 0)
3024 setEncoding(QString::null, false);
3026 // strip of the language to get the raw encoding again.
3027 QString enc = KGlobal::charsets()->encodingForName(d->m_paSetEncoding->currentText());
3028 setEncoding(enc, true);
3032 void KHTMLPart::slotUseStylesheet()
3034 if (d->m_doc && d->m_paUseStylesheet->currentText() != d->m_sheetUsed) {
3035 d->m_sheetUsed = d->m_paUseStylesheet->currentText();
3036 d->m_doc->updateStyleSelector();
3040 void KHTMLPart::updateActions()
3042 bool frames = false;
3044 QValueList<khtml::ChildFrame>::ConstIterator it = d->m_frames.begin();
3045 QValueList<khtml::ChildFrame>::ConstIterator end = d->m_frames.end();
3046 for (; it != end; ++it )
3047 if ( (*it).m_type == khtml::ChildFrame::Frame )
3053 d->m_paViewFrame->setEnabled( frames );
3054 d->m_paSaveFrame->setEnabled( frames );
3057 d->m_paFind->setText( i18n( "&Find in Frame..." ) );
3059 d->m_paFind->setText( i18n( "&Find..." ) );
3061 KParts::Part *frame = 0;
3064 frame = currentFrame();
3066 bool enableFindAndSelectAll = true;
3069 enableFindAndSelectAll = frame->inherits( "KHTMLPart" );
3071 d->m_paFind->setEnabled( enableFindAndSelectAll );
3072 d->m_paSelectAll->setEnabled( enableFindAndSelectAll );
3074 bool enablePrintFrame = false;
3078 QObject *ext = KParts::BrowserExtension::childObject( frame );
3080 enablePrintFrame = ext->metaObject()->slotNames().contains( "print()" );
3083 d->m_paPrintFrame->setEnabled( enablePrintFrame );
3088 if ( d->m_doc && d->m_doc->isHTMLDocument() && static_cast<HTMLDocumentImpl*>(d->m_doc)->body() && !d->m_bClearing )
3089 bgURL = static_cast<HTMLDocumentImpl*>(d->m_doc)->body()->getAttribute( ATTR_BACKGROUND ).string();
3091 d->m_paSaveBackground->setEnabled( !bgURL.isEmpty() );
3096 bool KHTMLPart::requestFrame( khtml::RenderPart *frame, const QString &url, const QString &frameName,
3097 const QStringList ¶mNames, const QStringList ¶mValues, bool isIFrame )
3099 // kdDebug( 6050 ) << "childRequest( ..., " << url << ", " << frameName << " )" << endl;
3100 FrameIt it = d->m_frames.find( frameName );
3101 if ( it == d->m_frames.end() )
3103 khtml::ChildFrame child;
3104 // kdDebug( 6050 ) << "inserting new frame into frame map " << frameName << endl;
3105 child.m_name = frameName;
3106 it = d->m_frames.append( child );
3109 (*it).m_type = isIFrame ? khtml::ChildFrame::IFrame : khtml::ChildFrame::Frame;
3110 (*it).m_frame = frame;
3111 (*it).m_paramValues = paramNames;
3112 (*it).m_paramNames = paramValues;
3114 // Support for <frame src="javascript:string">
3115 if ( url.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 )
3117 if (!processObjectRequest(&(*it), "about:blank", "text/html" ))
3120 KHTMLPart *newPart = static_cast<KHTMLPart *>(&*(*it).m_part);
3121 newPart->replaceContentsWithScriptResult( url );
3126 return requestObject( &(*it), completeURL( url ));
3129 QString KHTMLPart::requestFrameName()
3132 return KWQ(this)->generateFrameName();
3134 return QString::fromLatin1("<!--frame %1-->").arg(d->m_frameNameId++);
3138 bool KHTMLPart::requestObject( khtml::RenderPart *frame, const QString &url, const QString &serviceType,
3139 const QStringList ¶mNames, const QStringList ¶mValues )
3141 khtml::ChildFrame child;
3142 QValueList<khtml::ChildFrame>::Iterator it = d->m_objects.append( child );
3143 (*it).m_frame = frame;
3144 (*it).m_type = khtml::ChildFrame::Object;
3145 (*it).m_paramNames = paramNames;
3146 (*it).m_paramValues = paramValues;
3147 (*it).m_hasFallbackContent = frame->hasFallbackContent();
3151 completedURL = completeURL(url);
3153 KParts::URLArgs args;
3154 args.serviceType = serviceType;
3155 return requestObject( &(*it), completedURL, args );
3158 bool KHTMLPart::requestObject( khtml::ChildFrame *child, const KURL &url, const KParts::URLArgs &_args )
3161 if (!checkLinkSecurity(url))
3164 if ( child->m_bPreloaded )
3166 // kdDebug(6005) << "KHTMLPart::requestObject preload" << endl;
3167 if ( child->m_frame && child->m_part && child->m_part->widget() )
3168 child->m_frame->setWidget( child->m_part->widget() );
3170 child->m_bPreloaded = false;
3174 KParts::URLArgs args( _args );
3178 child->m_run->abort();
3181 if ( child->m_part && !args.reload && urlcmp( child->m_part->url().url(), url.url(), true, true ) )
3182 args.serviceType = child->m_serviceType;
3184 child->m_args = args;
3185 child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
3186 child->m_serviceName = QString::null;
3187 if (!d->m_referrer.isEmpty() && !child->m_args.metaData().contains( "referrer" ))
3188 child->m_args.metaData()["referrer"] = d->m_referrer;
3191 child->m_args.metaData().insert("main_frame_request",
3192 parentPart() == 0 ? "TRUE":"FALSE");
3193 child->m_args.metaData().insert("ssl_was_in_use",
3194 d->m_ssl_in_use ? "TRUE":"FALSE");
3195 child->m_args.metaData().insert("ssl_activate_warnings", "TRUE");
3198 // We want a KHTMLPart if the HTML says <frame src=""> or <frame src="about:blank">
3199 if ((url.isEmpty() || url.url() == "about:blank") && args.serviceType.isEmpty())
3200 args.serviceType = QString::fromLatin1( "text/html" );
3203 return processObjectRequest( child, url, args.serviceType );
3205 if ( args.serviceType.isEmpty() ) {
3206 child->m_run = new KHTMLRun( this, child, url, child->m_args,
3207 child->m_type != khtml::ChildFrame::Frame );
3210 return processObjectRequest( child, url, args.serviceType );
3215 bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url, const QString &mimetype )
3217 //kdDebug( 6050 ) << "KHTMLPart::processObjectRequest trying to create part for " << mimetype << endl;
3219 // IMPORTANT: create a copy of the url here, because it is just a reference, which was likely to be given
3220 // by an emitting frame part (emit openURLRequest( blahurl, ... ) . A few lines below we delete the part
3221 // though -> the reference becomes invalid -> crash is likely
3224 // khtmlrun called us this way to indicate a loading error
3225 if ( d->m_onlyLocalReferences || ( url.isEmpty() && mimetype.isEmpty() ) )
3227 checkEmitLoadEvent();
3228 child->m_bCompleted = true;
3232 if (child->m_bNotify)
3234 child->m_bNotify = false;
3235 if ( !child->m_args.lockHistory() )
3236 emit d->m_extension->openURLNotify();
3240 if ( child->m_part )
3242 KHTMLPart *part = static_cast<KHTMLPart *>(&*child->m_part);
3243 if (part && part->inherits("KHTMLPart")) {
3244 KParts::URLArgs args;
3245 if (!d->m_referrer.isEmpty())
3246 args.metaData()["referrer"] = d->m_referrer;
3247 KWQ(part)->openURLRequest(url, args);
3252 KParts::ReadOnlyPart *part = KWQ(this)->createPart(*child, url, mimetype);
3253 KHTMLPart *khtml_part = static_cast<KHTMLPart *>(part);
3254 if (khtml_part && khtml_part->inherits("KHTMLPart"))
3255 khtml_part->childBegin();
3257 if ( !child->m_services.contains( mimetype ) )
3259 KParts::ReadOnlyPart *part = createPart( d->m_view->viewport(), child->m_name.ascii(), this, child->m_name.ascii(), mimetype, child->m_serviceName, child->m_services, child->m_params );
3263 checkEmitLoadEvent();
3268 if ( child->m_part )
3270 disconnectChild(child);
3272 partManager()->removePart( (KParts::ReadOnlyPart *)child->m_part );
3274 child->m_part->deref();
3277 child->m_serviceType = mimetype;
3278 if ( child->m_frame && part->widget() )
3279 child->m_frame->setWidget( part->widget() );
3282 if ( child->m_type != khtml::ChildFrame::Object )
3283 partManager()->addPart( part, false );
3285 // kdDebug(6005) << "AH! NO FRAME!!!!!" << endl;
3288 child->m_part = part;
3289 assert( ((void*) child->m_part) != 0);
3291 connectChild(child);
3296 child->m_extension = KParts::BrowserExtension::childObject( part );
3298 if ( child->m_extension )
3300 connect( child->m_extension, SIGNAL( openURLNotify() ),
3301 d->m_extension, SIGNAL( openURLNotify() ) );
3303 connect( child->m_extension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
3304 this, SLOT( slotChildURLRequest( const KURL &, const KParts::URLArgs & ) ) );
3306 connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
3307 d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
3308 connect( child->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
3309 d->m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
3311 connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
3312 d->m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
3313 connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
3314 d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
3315 connect( child->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
3316 d->m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
3317 connect( child->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
3318 d->m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
3320 connect( child->m_extension, SIGNAL( infoMessage( const QString & ) ),
3321 d->m_extension, SIGNAL( infoMessage( const QString & ) ) );
3323 child->m_extension->setBrowserInterface( d->m_extension->browserInterface() );
3328 checkEmitLoadEvent();
3329 // Some JS code in the load event may have destroyed the part
3330 // In that case, abort
3331 if ( !child->m_part )
3334 if ( child->m_bPreloaded )
3336 if ( child->m_frame && child->m_part )
3337 child->m_frame->setWidget( child->m_part->widget() );
3339 child->m_bPreloaded = false;
3343 child->m_args.reload = (d->m_cachePolicy == KIO::CC_Reload) || (d->m_cachePolicy == KIO::CC_Refresh);
3345 // make sure the part has a way to find out about the mimetype.
3346 // we actually set it in child->m_args in requestObject already,
3347 // but it's useless if we had to use a KHTMLRun instance, as the
3348 // point the run object is to find out exactly the mimetype.
3349 child->m_args.serviceType = mimetype;
3351 child->m_bCompleted = false;
3352 if ( child->m_extension )
3353 child->m_extension->setURLArgs( child->m_args );
3356 // In these cases, the synchronous load would have finished
3357 // before we could connect the signals, so make sure to send the
3358 // completed() signal for the child by hand
3359 // FIXME: In this case the KHTMLPart will have finished loading before
3360 // it's being added to the child list. It would be a good idea to
3361 // create the child first, then invoke the loader separately
3362 if (url.isEmpty() || url.url() == "about:blank") {
3363 ReadOnlyPart *readOnlyPart = child->m_part;
3364 KHTMLPart *part = static_cast<KHTMLPart *>(readOnlyPart);
3365 if (part && part->inherits("KHTMLPart")) {
3367 part->checkCompleted();
3371 if(url.protocol() == "javascript" || url.url() == "about:blank") {
3372 if (!child->m_part->inherits("KHTMLPart"))
3375 KHTMLPart* p = static_cast<KHTMLPart*>(static_cast<KParts::ReadOnlyPart *>(child->m_part));
3378 if (d->m_doc && p->d->m_doc)
3379 p->d->m_doc->setBaseURL(d->m_doc->baseURL());
3380 if (!url.url().startsWith("about:")) {
3381 p->write(url.path());
3388 else if ( !url.isEmpty() )
3390 //kdDebug( 6050 ) << "opening " << url.url() << " in frame " << child->m_part << endl;
3391 return child->m_part->openURL( url );
3400 KParts::ReadOnlyPart *KHTMLPart::createPart( QWidget *parentWidget, const char *widgetName,
3401 QObject *parent, const char *name, const QString &mimetype,
3402 QString &serviceName, QStringList &serviceTypes,
3403 const QStringList ¶ms )
3406 if ( !serviceName.isEmpty() )
3407 constr.append( QString::fromLatin1( "Name == '%1'" ).arg( serviceName ) );
3409 KTrader::OfferList offers = KTrader::self()->query( mimetype, "KParts/ReadOnlyPart", constr, QString::null );
3411 if ( offers.isEmpty() )
3414 KService::Ptr service = *offers.begin();
3416 KLibFactory *factory = KLibLoader::self()->factory( QFile::encodeName(service->library()) );
3421 KParts::ReadOnlyPart *res = 0L;
3423 const char *className = "KParts::ReadOnlyPart";
3424 if ( service->serviceTypes().contains( "Browser/View" ) )
3425 className = "Browser/View";
3427 if ( factory->inherits( "KParts::Factory" ) )
3428 res = static_cast<KParts::ReadOnlyPart *>(static_cast<KParts::Factory *>( factory )->createPart( parentWidget, widgetName, parent, name, className, params ));
3430 res = static_cast<KParts::ReadOnlyPart *>(factory->create( parentWidget, widgetName, className ));
3435 serviceTypes = service->serviceTypes();
3436 serviceName = service->name();
3441 KParts::PartManager *KHTMLPart::partManager()
3443 if ( !d->m_manager )
3445 d->m_manager = new KParts::PartManager( d->m_view->topLevelWidget(), this, "khtml part manager" );
3446 d->m_manager->setAllowNestedParts( true );
3447 connect( d->m_manager, SIGNAL( activePartChanged( KParts::Part * ) ),
3448 this, SLOT( slotActiveFrameChanged( KParts::Part * ) ) );
3449 connect( d->m_manager, SIGNAL( partRemoved( KParts::Part * ) ),
3450 this, SLOT( slotPartRemoved( KParts::Part * ) ) );
3453 return d->m_manager;
3458 void KHTMLPart::submitFormAgain()
3460 if( d->m_doc && !d->m_doc->parsing() && d->m_submitForm)
3461 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 );
3463 delete d->m_submitForm;
3464 d->m_submitForm = 0;
3465 disconnect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
3468 void KHTMLPart::submitForm( const char *action, const QString &url, const FormData &formData, const QString &_target, const QString& contentType, const QString& boundary )
3470 kdDebug(6000) << this << ": KHTMLPart::submitForm target=" << _target << " url=" << url << endl;
3471 KURL u = completeURL( url );
3475 // ### ERROR HANDLING!
3480 // Form security checks
3483 /* This is separate for a reason. It has to be _before_ all script, etc,
3484 * AND I don't want to break anything that uses checkLinkSecurity() in
3488 // This causes crashes... needs to be fixed.
3489 if (!d->m_submitForm && u.protocol() != "https" && u.protocol() != "mailto") {
3490 if (d->m_ssl_in_use) { // Going from SSL -> nonSSL
3491 int rc = KMessageBox::warningContinueCancel(NULL, i18n("Warning: This is a secure form but it is attempting to send your data back unencrypted."
3492 "\nA third party may be able to intercept and view this information."
3493 "\nAre you sure you wish to continue?"),
3495 if (rc == KMessageBox::Cancel)
3497 } else { // Going from nonSSL -> nonSSL
3498 KSSLSettings kss(true);
3499 if (kss.warnOnUnencrypted()) {
3500 int rc = KMessageBox::warningContinueCancel(NULL,
3501 i18n("Warning: Your data is about to be transmitted across the network unencrypted."
3502 "\nAre you sure you wish to continue?"),
3505 "WarnOnUnencryptedForm");
3506 // Move this setting into KSSL instead
3507 KConfig *config = kapp->config();
3508 QString grpNotifMsgs = QString::fromLatin1("Notification Messages");
3509 KConfigGroupSaver saver( config, grpNotifMsgs );
3511 if (!config->readBoolEntry("WarnOnUnencryptedForm", true)) {
3512 config->deleteEntry("WarnOnUnencryptedForm");
3514 kss.setWarnOnUnencrypted(false);
3517 if (rc == KMessageBox::Cancel)
3523 if (!d->m_submitForm && u.protocol() == "mailto") {
3524 int rc = KMessageBox::warningContinueCancel(NULL,
3525 i18n("This site is attempting to submit form data via email."),
3528 "WarnTriedEmailSubmit");
3530 if (rc == KMessageBox::Cancel) {
3535 // End form security checks
3537 #endif // APPLE_CHANGES
3539 QString urlstring = u.url();
3541 if ( urlstring.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
3542 urlstring = KURL::decode_string(urlstring);
3543 d->m_executingJavaScriptFormAction = true;
3544 executeScript( urlstring.right( urlstring.length() - 11) );
3545 d->m_executingJavaScriptFormAction = false;
3550 if (!checkLinkSecurity(u,
3551 i18n( "<qt>The form will be submitted to <BR><B>%1</B><BR>on your local filesystem.<BR>Do you want to submit the form?" ),
3556 KParts::URLArgs args;
3558 if (!d->m_referrer.isEmpty())
3559 args.metaData()["referrer"] = d->m_referrer;
3562 args.metaData().insert("main_frame_request",
3563 parentPart() == 0 ? "TRUE":"FALSE");
3564 args.metaData().insert("ssl_was_in_use", d->m_ssl_in_use ? "TRUE":"FALSE");
3565 args.metaData().insert("ssl_activate_warnings", "TRUE");
3567 args.frameName = _target.isEmpty() ? d->m_doc->baseTarget() : _target ;
3569 // Handle mailto: forms
3570 if (u.protocol() == "mailto") {
3571 // 1) Check for attach= and strip it
3572 QString q = u.query().mid(1);
3573 QStringList nvps = QStringList::split("&", q);
3574 bool triedToAttach = false;
3576 for (QStringList::Iterator nvp = nvps.begin(); nvp != nvps.end(); ++nvp) {
3577 QStringList pair = QStringList::split("=", *nvp);
3578 if (pair.count() >= 2) {
3579 if (pair.first().lower() == "attach") {
3580 nvp = nvps.remove(nvp);
3581 triedToAttach = true;
3588 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");
3593 if (contentType.lower() == "multipart/form-data") {
3594 // FIXME: is this correct? I suspect not
3595 bodyEnc = KURL::encode_string(formData.flattenToString());
3596 } else if (contentType.lower() == "text/plain") {
3597 // Convention seems to be to decode, and s/&/\n/
3598 QString tmpbody = formData.flattenToString();
3599 tmpbody.replace('&', '\n');
3600 tmpbody.replace('+', ' ');
3601 tmpbody = KURL::decode_string(tmpbody); // Decode the rest of it
3602 bodyEnc = KURL::encode_string(tmpbody); // Recode for the URL
3604 bodyEnc = KURL::encode_string(formData.flattenToString());
3607 nvps.append(QString("body=%1").arg(bodyEnc));
3612 if ( strcmp( action, "get" ) == 0 ) {
3613 if (u.protocol() != "mailto")
3614 u.setQuery( formData.flattenToString() );
3615 args.setDoPost( false );
3619 args.postData = formData;
3621 args.postData = formData.flatten();
3623 args.setDoPost( true );
3625 // construct some user headers if necessary
3626 if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
3627 args.setContentType( "Content-Type: application/x-www-form-urlencoded" );
3628 else // contentType must be "multipart/form-data"
3629 args.setContentType( "Content-Type: " + contentType + "; boundary=" + boundary );
3632 if ( d->m_doc->parsing() || d->m_runningScripts > 0 ) {
3633 if( d->m_submitForm ) {
3634 kdDebug(6000) << "KHTMLPart::submitForm ABORTING!" << endl;
3637 d->m_submitForm = new KHTMLPartPrivate::SubmitForm;
3638 d->m_submitForm->submitAction = action;
3639 d->m_submitForm->submitUrl = url;
3640 d->m_submitForm->submitFormData = formData;
3641 d->m_submitForm->target = _target;
3642 d->m_submitForm->submitContentType = contentType;
3643 d->m_submitForm->submitBoundary = boundary;
3644 connect(this, SIGNAL(completed()), this, SLOT(submitFormAgain()));
3649 KWQ(this)->submitForm( u, args);
3651 emit d->m_extension->openURLRequest( u, args );
3658 void KHTMLPart::popupMenu( const QString &linkUrl )
3662 if ( linkUrl.isEmpty() ) // click on background
3663 popupURL = this->url();
3664 else { // click on link
3665 popupURL = completeURL( linkUrl );
3666 linkKURL = popupURL;
3669 KXMLGUIClient *client = new KHTMLPopupGUIClient( this, d->m_popupMenuXML, linkKURL );
3671 emit d->m_extension->popupMenu( client, QCursor::pos(), popupURL,
3672 QString::fromLatin1( "text/html" ), S_IFREG /*always a file*/ );
3676 emit popupMenu(linkUrl, QCursor::pos());
3681 void KHTMLPart::slotParentCompleted()
3683 if ( d->m_scheduledRedirection != noRedirectionScheduled && !d->m_redirectionTimer.isActive() )
3685 // kdDebug(6050) << this << ": Child redirection -> " << d->m_redirectURL << endl;
3686 d->m_redirectionTimer.start( (int)(1000 * d->m_delayRedirect), true );
3690 void KHTMLPart::slotChildStarted( KIO::Job *job )
3692 khtml::ChildFrame *child = childFrame( sender() );
3696 child->m_bCompleted = false;
3698 if ( d->m_bComplete )
3701 // WABA: Looks like this belongs somewhere else
3702 if ( !parentPart() ) // "toplevel" html document? if yes, then notify the hosting browser about the document (url) changes
3704 emit d->m_extension->openURLNotify();
3707 d->m_bComplete = false;
3708 emit started( job );
3712 void KHTMLPart::slotChildCompleted()
3714 slotChildCompleted( false );
3717 void KHTMLPart::slotChildCompleted( bool complete )
3719 khtml::ChildFrame *child = childFrame( sender() );
3723 child->m_bCompleted = true;
3724 child->m_args = KParts::URLArgs();
3726 if ( complete && parentPart() == 0 )
3727 d->m_bPendingChildRedirection = true;
3734 void KHTMLPart::slotChildURLRequest( const KURL &url, const KParts::URLArgs &args )
3736 khtml::ChildFrame *child = childFrame( sender()->parent() );
3738 QString frameName = args.frameName.lower();
3739 if ( !frameName.isEmpty() )
3741 if ( frameName == QString::fromLatin1( "_top" ) )
3743 emit d->m_extension->openURLRequest( url, args );
3746 else if ( frameName == QString::fromLatin1( "_blank" ) )
3748 emit d->m_extension->createNewWindow( url, args );
3751 else if ( frameName == QString::fromLatin1( "_parent" ) )
3753 KParts::URLArgs newArgs( args );
3754 newArgs.frameName = QString::null;
3756 emit d->m_extension->openURLRequest( url, newArgs );
3759 else if ( frameName != QString::fromLatin1( "_self" ) )
3761 khtml::ChildFrame *_frame = recursiveFrameRequest( url, args );
3765 emit d->m_extension->openURLRequest( url, args );
3773 // TODO: handle child target correctly! currently the script are always executed fur the parent
3774 QString urlStr = url.url();
3775 if ( urlStr.find( QString::fromLatin1( "javascript:" ), 0, false ) == 0 ) {
3776 executeScript( KURL::decode_string( urlStr.right( urlStr.length() - 11) ) );
3781 // Inform someone that we are about to show something else.
3782 child->m_bNotify = true;
3783 requestObject( child, url, args );
3784 } else if ( frameName==QString::fromLatin1("_self") ) // this is for embedded objects (via <object>) which want to replace the current document
3786 KParts::URLArgs newArgs( args );
3787 newArgs.frameName = QString::null;
3788 emit d->m_extension->openURLRequest( url, newArgs );
3792 #endif // APPLE_CHANGES
3794 khtml::ChildFrame *KHTMLPart::childFrame( const QObject *obj )
3796 assert( obj->inherits( "KParts::ReadOnlyPart" ) );
3797 const ReadOnlyPart *part = static_cast<const ReadOnlyPart *>( obj );
3799 FrameIt it = d->m_frames.begin();
3800 FrameIt end = d->m_frames.end();
3801 for (; it != end; ++it )
3802 if ( static_cast<ReadOnlyPart *>((*it).m_part) == part )
3805 it = d->m_objects.begin();
3806 end = d->m_objects.end();
3807 for (; it != end; ++it )
3808 if ( static_cast<ReadOnlyPart *>((*it).m_part) == part )
3814 KHTMLPart *KHTMLPart::findFrame( const QString &f )
3817 kdDebug() << "KHTMLPart::findFrame '" << f << "'" << endl;
3818 FrameIt it2 = d->m_frames.begin();
3819 FrameIt end = d->m_frames.end();
3820 for (; it2 != end; ++it2 )
3821 kdDebug() << " - having frame '" << (*it2).m_name << "'" << endl;
3824 // ### http://www.w3.org/TR/html4/appendix/notes.html#notes-frames
3825 ConstFrameIt it = d->m_frames.find( f );
3826 if ( it == d->m_frames.end() )
3828 //kdDebug() << "KHTMLPart::findFrame frame " << f << " not found" << endl;
3832 KParts::ReadOnlyPart *p = (*it).m_part;
3833 if ( p && p->inherits( "KHTMLPart" ))
3835 //kdDebug() << "KHTMLPart::findFrame frame " << f << " is a KHTMLPart, ok" << endl;
3836 return (KHTMLPart*)p;
3842 kdWarning() << "KHTMLPart::findFrame frame " << f << " found but isn't a KHTMLPart ! " << p->className() << endl;
3844 kdWarning() << "KHTMLPart::findFrame frame " << f << " found but m_part=0L" << endl;
3853 KParts::ReadOnlyPart *KHTMLPart::currentFrame() const
3855 KParts::ReadOnlyPart* part = (KParts::ReadOnlyPart*)(this);
3856 // Find active part in our frame manager, in case we are a frameset
3857 // and keep doing that (in case of nested framesets).
3858 // Just realized we could also do this recursively, calling part->currentFrame()...
3859 while ( part && part->inherits("KHTMLPart") &&
3860 static_cast<KHTMLPart *>(part)->d->m_frames.count() > 0 ) {
3861 KHTMLPart* frameset = static_cast<KHTMLPart *>(part);
3862 part = static_cast<KParts::ReadOnlyPart *>(frameset->partManager()->activePart());
3863 if ( !part ) return frameset;
3868 #endif // APPLE_CHANGES
3870 bool KHTMLPart::frameExists( const QString &frameName )
3872 ConstFrameIt it = d->m_frames.find( frameName );
3873 if ( it == d->m_frames.end() )
3876 // WABA: We only return true if the child actually has a frame
3877 // set. Otherwise we might find our preloaded-selve.
3878 // This happens when we restore the frameset.
3879 return (!(*it).m_frame.isNull());
3882 KHTMLPart *KHTMLPart::parentPart() const
3884 if ( !parent() || !parent()->inherits( "KHTMLPart" ) )
3887 return (KHTMLPart *)parent();
3892 khtml::ChildFrame *KHTMLPart::recursiveFrameRequest( const KURL &url, const KParts::URLArgs &args,
3895 FrameIt it = d->m_frames.find( args.frameName );
3897 if ( it != d->m_frames.end() )
3900 it = d->m_frames.begin();
3901 FrameIt end = d->m_frames.end();
3902 for (; it != end; ++it )
3903 if ( (*it).m_part && (*it).m_part->inherits( "KHTMLPart" ) )
3905 KHTMLPart *childPart = (KHTMLPart *)(KParts::ReadOnlyPart *)(*it).m_part;
3907 khtml::ChildFrame *res = childPart->recursiveFrameRequest( url, args, false );
3911 childPart->requestObject( res, url, args );
3915 if ( parentPart() && callParent )
3917 khtml::ChildFrame *res = parentPart()->recursiveFrameRequest( url, args );
3920 parentPart()->requestObject( res, url, args );
3928 void KHTMLPart::saveState( QDataStream &stream )
3930 kdDebug( 6050 ) << "KHTMLPart::saveState saving URL " << m_url.url() << endl;
3932 stream << m_url << (Q_INT32)d->m_view->contentsX() << (Q_INT32)d->m_view->contentsY()
3933 << (Q_INT32) d->m_view->contentsWidth() << (Q_INT32) d->m_view->contentsHeight() << (Q_INT32) d->m_view->marginWidth() << (Q_INT32) d->m_view->marginHeight();
3935 // save link cursor position
3936 int focusNodeNumber;
3937 if (!d->m_focusNodeRestored)
3938 focusNodeNumber = d->m_focusNodeNumber;
3939 else if (d->m_doc->focusNode())
3940 focusNodeNumber = d->m_doc->nodeAbsIndex(d->m_doc->focusNode());
3942 focusNodeNumber = -1;
3943 stream << focusNodeNumber;
3945 // Save the doc's cache id.
3946 stream << d->m_cacheId;
3948 // Save the state of the document (Most notably the state of any forms)
3949 QStringList docState;
3952 docState = d->m_doc->docState();
3954 stream << d->m_encoding << d->m_sheetUsed << docState;
3956 stream << d->m_zoomFactor;
3959 stream << d->m_ssl_in_use
3960 << d->m_ssl_peer_certificate
3961 << d->m_ssl_peer_chain
3964 << d->m_ssl_cipher_desc
3965 << d->m_ssl_cipher_version
3966 << d->m_ssl_cipher_used_bits
3967 << d->m_ssl_cipher_bits
3968 << d->m_ssl_cert_state;
3971 QStringList frameNameLst, frameServiceTypeLst, frameServiceNameLst;
3972 KURL::List frameURLLst;
3973 QValueList<QByteArray> frameStateBufferLst;
3975 ConstFrameIt it = d->m_frames.begin();
3976 ConstFrameIt end = d->m_frames.end();
3977 for (; it != end; ++it )
3979 if ( !(*it).m_part )
3982 frameNameLst << (*it).m_name;
3983 frameServiceTypeLst << (*it).m_serviceType;
3984 frameServiceNameLst << (*it).m_serviceName;
3985 frameURLLst << (*it).m_part->url();
3988 QDataStream frameStream( state, IO_WriteOnly );
3990 if ( (*it).m_extension )
3991 (*it).m_extension->saveState( frameStream );
3993 frameStateBufferLst << state;
3997 stream << (Q_UINT32) frameNameLst.count();
3998 stream << frameNameLst << frameServiceTypeLst << frameServiceNameLst << frameURLLst << frameStateBufferLst;
4001 void KHTMLPart::restoreState( QDataStream &stream )
4004 Q_INT32 xOffset, yOffset, wContents, hContents, mWidth, mHeight;
4005 Q_UINT32 frameCount;
4006 QStringList frameNames, frameServiceTypes, docState, frameServiceNames;
4007 KURL::List frameURLs;
4008 QValueList<QByteArray> frameStateBuffers;
4009 QValueList<int> fSizes;
4010 QString encoding, sheetUsed;
4011 long old_cacheId = d->m_cacheId;
4013 stream >> u >> xOffset >> yOffset >> wContents >> hContents >> mWidth >> mHeight;
4015 d->m_view->setMarginWidth( mWidth );
4016 d->m_view->setMarginHeight( mHeight );
4018 // restore link cursor position
4019 // nth node is active. value is set in checkCompleted()
4020 stream >> d->m_focusNodeNumber;
4021 d->m_focusNodeRestored = false;
4022 kdDebug(6050)<<"new focus Node number is:"<<d->m_focusNodeNumber<<endl;
4024 stream >> d->m_cacheId;
4026 stream >> encoding >> sheetUsed >> docState;
4027 d->m_encoding = encoding;
4028 d->m_sheetUsed = sheetUsed;
4031 stream >> zoomFactor;
4032 setZoomFactor(zoomFactor);
4035 stream >> d->m_ssl_in_use
4036 >> d->m_ssl_peer_certificate
4037 >> d->m_ssl_peer_chain
4040 >> d->m_ssl_cipher_desc
4041 >> d->m_ssl_cipher_version
4042 >> d->m_ssl_cipher_used_bits
4043 >> d->m_ssl_cipher_bits
4044 >> d->m_ssl_cert_state;
4046 d->m_paSecurity->setIcon( d->m_ssl_in_use ? "encrypted" : "decrypted" );
4048 stream >> frameCount >> frameNames >> frameServiceTypes >> frameServiceNames
4049 >> frameURLs >> frameStateBuffers;
4051 d->m_bComplete = false;
4052 d->m_bLoadEventEmitted = false;
4054 // kdDebug( 6050 ) << "restoreStakte() docState.count() = " << docState.count() << endl;
4055 // kdDebug( 6050 ) << "m_url " << m_url.url() << " <-> " << u.url() << endl;
4056 // kdDebug( 6050 ) << "m_frames.count() " << d->m_frames.count() << " <-> " << frameCount << endl;
4058 if (d->m_cacheId == old_cacheId)
4061 cancelRedirection();
4063 FrameIt fIt = d->m_frames.begin();
4064 FrameIt fEnd = d->m_frames.end();
4066 for (; fIt != fEnd; ++fIt )
4067 (*fIt).m_bCompleted = false;
4069 fIt = d->m_frames.begin();
4071 QStringList::ConstIterator fNameIt = frameNames.begin();
4072 QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
4073 QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
4074 KURL::List::ConstIterator fURLIt = frameURLs.begin();
4075 QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
4077 for (; fIt != fEnd; ++fIt, ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
4079 khtml::ChildFrame *child = &(*fIt);
4081 // kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
4083 if ( child->m_name != *fNameIt || child->m_serviceType != *fServiceTypeIt )
4085 child->m_bPreloaded = true;
4086 child->m_name = *fNameIt;
4087 child->m_serviceName = *fServiceNameIt;
4088 processObjectRequest( child, *fURLIt, *fServiceTypeIt );
4091 if ( child->m_part )
4093 child->m_bCompleted = false;
4094 if ( child->m_extension && !(*fBufferIt).isEmpty() )
4096 QDataStream frameStream( *fBufferIt, IO_ReadOnly );
4097 child->m_extension->restoreState( frameStream );
4100 child->m_part->openURL( *fURLIt );
4104 KParts::URLArgs args( d->m_extension->urlArgs() );
4105 args.xOffset = xOffset;
4106 args.yOffset = yOffset;
4107 args.docState = docState; // WABA: How are we going to restore this??
4108 d->m_extension->setURLArgs( args );
4110 d->m_view->resizeContents( wContents, hContents);
4111 d->m_view->setContentsPos( xOffset, yOffset );
4117 // We must force a clear because we want to be sure to delete all
4119 d->m_bCleared = false;
4121 d->m_encoding = encoding;
4122 d->m_sheetUsed = sheetUsed;
4124 QStringList::ConstIterator fNameIt = frameNames.begin();
4125 QStringList::ConstIterator fNameEnd = frameNames.end();
4127 QStringList::ConstIterator fServiceTypeIt = frameServiceTypes.begin();
4128 QStringList::ConstIterator fServiceNameIt = frameServiceNames.begin();
4129 KURL::List::ConstIterator fURLIt = frameURLs.begin();
4130 QValueList<QByteArray>::ConstIterator fBufferIt = frameStateBuffers.begin();
4132 for (; fNameIt != fNameEnd; ++fNameIt, ++fServiceTypeIt, ++fServiceNameIt, ++fURLIt, ++fBufferIt )
4134 khtml::ChildFrame newChild;
4135 newChild.m_bPreloaded = true;
4136 newChild.m_name = *fNameIt;
4137 newChild.m_serviceName = *fServiceNameIt;
4139 // kdDebug( 6050 ) << *fNameIt << " ---- " << *fServiceTypeIt << endl;
4141 FrameIt childFrame = d->m_frames.append( newChild );
4143 processObjectRequest( &(*childFrame), *fURLIt, *fServiceTypeIt );
4145 (*childFrame).m_bPreloaded = true;
4147 if ( (*childFrame).m_part )
4149 if ( (*childFrame).m_extension )
4150 if ( (*childFrame).m_extension && !(*fBufferIt).isEmpty() )
4152 QDataStream frameStream( *fBufferIt, IO_ReadOnly );
4153 (*childFrame).m_extension->restoreState( frameStream );
4156 (*childFrame).m_part->openURL( *fURLIt );
4160 KParts::URLArgs args( d->m_extension->urlArgs() );
4161 args.xOffset = xOffset;
4162 args.yOffset = yOffset;
4163 args.docState = docState;
4164 d->m_extension->setURLArgs( args );
4165 if (!KHTMLPageCache::self()->isValid(d->m_cacheId))
4167 d->m_restored = true;
4169 d->m_restored = false;
4179 void KHTMLPart::show()
4185 void KHTMLPart::hide()
4191 #endif // APPLE_CHANGES
4193 DOM::Node KHTMLPart::nodeUnderMouse() const
4195 return d->m_view->nodeUnderMouse();
4198 void KHTMLPart::emitSelectionChanged()
4201 emit d->m_extension->enableAction( "copy", hasSelection() );
4202 emit d->m_extension->selectionInfo( selectedText() );
4203 emit selectionChanged();
4207 int KHTMLPart::zoomFactor() const
4209 return d->m_zoomFactor;
4212 // ### make the list configurable ?
4213 static const int zoomSizes[] = { 20, 40, 60, 80, 90, 95, 100, 105, 110, 120, 140, 160, 180, 200, 250, 300 };
4214 static const int zoomSizeCount = (sizeof(zoomSizes) / sizeof(int));
4215 static const int minZoom = 20;
4216 static const int maxZoom = 300;
4218 void KHTMLPart::slotIncZoom()
4220 int zoomFactor = d->m_zoomFactor;
4222 if (zoomFactor < maxZoom) {
4223 // find the entry nearest to the given zoomsizes
4224 for (int i = 0; i < zoomSizeCount; ++i)
4225 if (zoomSizes[i] > zoomFactor) {
4226 zoomFactor = zoomSizes[i];
4229 setZoomFactor(zoomFactor);
4233 void KHTMLPart::slotDecZoom()
4235 int zoomFactor = d->m_zoomFactor;
4236 if (zoomFactor > minZoom) {
4237 // find the entry nearest to the given zoomsizes
4238 for (int i = zoomSizeCount-1; i >= 0; --i)
4239 if (zoomSizes[i] < zoomFactor) {
4240 zoomFactor = zoomSizes[i];
4243 setZoomFactor(zoomFactor);
4247 void KHTMLPart::setZoomFactor (int percent)
4249 #if !APPLE_CHANGES // limits are client's responsibility
4250 if (percent < minZoom) percent = minZoom;
4251 if (percent > maxZoom) percent = maxZoom;
4254 if (d->m_zoomFactor == percent) return;
4255 d->m_zoomFactor = percent;
4259 QApplication::setOverrideCursor( waitCursor );
4261 d->m_doc->recalcStyle( NodeImpl::Force );
4263 QApplication::restoreOverrideCursor();
4267 ConstFrameIt it = d->m_frames.begin();
4268 ConstFrameIt end = d->m_frames.end();
4269 for (; it != end; ++it )
4270 if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
4271 KParts::ReadOnlyPart* p = ( *it ).m_part;
4272 static_cast<KHTMLPart*>( p )->setZoomFactor(d->m_zoomFactor);
4276 d->m_paDecZoomFactor->setEnabled( d->m_zoomFactor > minZoom );
4277 d->m_paIncZoomFactor->setEnabled( d->m_zoomFactor < maxZoom );
4280 if (d->m_doc && d->m_doc->renderer() && d->m_doc->renderer()->needsLayout())
4284 void KHTMLPart::setJSStatusBarText( const QString &text )
4286 d->m_kjsStatusBarText = text;
4287 emit setStatusBarText( d->m_kjsStatusBarText );
4290 void KHTMLPart::setJSDefaultStatusBarText( const QString &text )
4292 d->m_kjsDefaultStatusBarText = text;
4293 emit setStatusBarText( d->m_kjsDefaultStatusBarText );
4296 QString KHTMLPart::jsStatusBarText() const
4298 return d->m_kjsStatusBarText;
4301 QString KHTMLPart::jsDefaultStatusBarText() const
4303 return d->m_kjsDefaultStatusBarText;
4306 QString KHTMLPart::referrer() const
4308 return d->m_referrer;
4311 QString KHTMLPart::lastModified() const
4313 return d->m_lastModified;
4318 void KHTMLPart::slotLoadImages()
4321 d->m_doc->docLoader()->setAutoloadImages( !d->m_doc->docLoader()->autoloadImages() );
4323 ConstFrameIt it = d->m_frames.begin();
4324 ConstFrameIt end = d->m_frames.end();
4325 for (; it != end; ++it )
4326 if ( !( *it ).m_part.isNull() && ( *it ).m_part->inherits( "KHTMLPart" ) ) {
4327 KParts::ReadOnlyPart* p = ( *it ).m_part;
4328 static_cast<KHTMLPart*>( p )->slotLoadImages();
4334 void KHTMLPart::reparseConfiguration()
4337 setAutoloadImages( settings->autoLoadImages() );
4339 d->m_doc->docLoader()->setShowAnimations( settings->showAnimations() );
4341 d->m_bJScriptEnabled = settings->isJavaScriptEnabled(m_url.host());
4342 d->m_bJScriptDebugEnabled = settings->isJavaScriptDebugEnabled();
4343 d->m_bJavaEnabled = settings->isJavaEnabled(m_url.host());
4344 d->m_bPluginsEnabled = settings->isPluginsEnabled(m_url.host());
4345 delete d->m_settings;
4346 d->m_settings = new KHTMLSettings(*KHTMLFactory::defaultHTMLSettings());
4348 QString userStyleSheet = KHTMLFactory::defaultHTMLSettings()->userStyleSheet();
4350 setAutoloadImages( d->m_settings->autoLoadImages() );
4352 d->m_doc->docLoader()->setShowAnimations( d->m_settings->showAnimations() );
4354 d->m_bJScriptEnabled = d->m_settings->isJavaScriptEnabled(m_url.host());
4355 d->m_bJScriptDebugEnabled = d->m_settings->isJavaScriptDebugEnabled();
4356 d->m_bJavaEnabled = d->m_settings->isJavaEnabled(m_url.host());
4357 d->m_bPluginsEnabled = d->m_settings->isPluginsEnabled(m_url.host());
4359 QString userStyleSheet = d->m_settings->userStyleSheet();
4361 if ( !userStyleSheet.isEmpty() )
4362 setUserStyleSheet( KURL( userStyleSheet ) );
4364 setUserStyleSheet( QString() );
4367 QApplication::setOverrideCursor( waitCursor );
4369 if(d->m_doc) d->m_doc->updateStyleSelector();
4371 QApplication::restoreOverrideCursor();
4375 QStringList KHTMLPart::frameNames() const
4379 ConstFrameIt it = d->m_frames.begin();
4380 ConstFrameIt end = d->m_frames.end();
4381 for (; it != end; ++it )
4382 if (!(*it).m_bPreloaded)
4383 res += (*it).m_name;
4388 QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
4390 QPtrList<KParts::ReadOnlyPart> res;
4392 ConstFrameIt it = d->m_frames.begin();
4393 ConstFrameIt end = d->m_frames.end();
4394 for (; it != end; ++it )
4395 if (!(*it).m_bPreloaded)
4396 res.append( (*it).m_part );
4401 KHTMLPart *KHTMLPart::childFrameNamed(const QString &name) const
4403 FrameList::Iterator it = d->m_frames.find(name);
4404 if (it != d->m_frames.end())
4405 return static_cast<KHTMLPart *>(&*(*it).m_part);
4412 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )