kjs_window.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2000-2003 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2001-2003 David Faure (faure@kde.org)
00006  *  Copyright (C) 2003 Apple Computer, Inc.
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public
00019  *  License along with this library; if not, write to the Free Software
00020  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  */
00022 #include "config.h"
00023 
00024 #include "khtmlview.h"
00025 #include "khtml_part.h"
00026 #include "khtmlpart_p.h"
00027 #include "khtml_settings.h"
00028 #include "xml/dom2_eventsimpl.h"
00029 #include "xml/dom_docimpl.h"
00030 #include "misc/htmltags.h"
00031 #include "html/html_documentimpl.h"
00032 #include "rendering/render_frames.h"
00033 
00034 #include <qstylesheet.h>
00035 #include <qtimer.h>
00036 #include <qpaintdevicemetrics.h>
00037 #include <qapplication.h>
00038 #include <kdebug.h>
00039 #include <kmessagebox.h>
00040 #include <kinputdialog.h>
00041 #include <klocale.h>
00042 #include <kmdcodec.h>
00043 #include <kparts/browserinterface.h>
00044 #include <kwin.h>
00045 
00046 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00047 #include <kwinmodule.h> // schroder
00048 #endif
00049 
00050 #ifndef KONQ_EMBEDDED
00051 #include <kbookmarkmanager.h>
00052 #endif
00053 #include <kglobalsettings.h>
00054 #include <assert.h>
00055 #include <qstyle.h>
00056 #include <qobjectlist.h>
00057 #include <kstringhandler.h>
00058 
00059 #include "kjs_proxy.h"
00060 #include "kjs_window.h"
00061 #include "kjs_navigator.h"
00062 #include "kjs_mozilla.h"
00063 #include "kjs_html.h"
00064 #include "kjs_range.h"
00065 #include "kjs_traversal.h"
00066 #include "kjs_css.h"
00067 #include "kjs_events.h"
00068 #include "kjs_views.h"
00069 #include "xmlhttprequest.h"
00070 #include "xmlserializer.h"
00071 #include "domparser.h"
00072 
00073 using namespace KJS;
00074 
00075 namespace KJS {
00076 
00077   class History : public ObjectImp {
00078     friend class HistoryFunc;
00079   public:
00080     History(ExecState *exec, KHTMLPart *p)
00081       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00082     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00083     Value getValueProperty(ExecState *exec, int token) const;
00084     virtual const ClassInfo* classInfo() const { return &info; }
00085     static const ClassInfo info;
00086     enum { Back, Forward, Go, Length };
00087   private:
00088     QGuardedPtr<KHTMLPart> part;
00089   };
00090 
00091   class External : public ObjectImp {
00092     friend class ExternalFunc;
00093   public:
00094     External(ExecState *exec, KHTMLPart *p)
00095       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00096     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00097     virtual const ClassInfo* classInfo() const { return &info; }
00098     static const ClassInfo info;
00099     enum { AddFavorite };
00100   private:
00101     QGuardedPtr<KHTMLPart> part;
00102   };
00103 
00104   class FrameArray : public ObjectImp {
00105   public:
00106     FrameArray(ExecState *exec, KHTMLPart *p)
00107       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00108     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00109   private:
00110     QGuardedPtr<KHTMLPart> part;
00111   };
00112 
00113 #ifdef Q_WS_QWS
00114   class KonquerorFunc : public DOMFunction {
00115   public:
00116     KonquerorFunc(ExecState *exec, const Konqueror* k, const char* name)
00117       : DOMFunction(exec), konqueror(k), m_name(name) { }
00118     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
00119 
00120   private:
00121     const Konqueror* konqueror;
00122     QCString m_name;
00123   };
00124 #endif
00125 } // namespace KJS
00126 
00127 #include "kjs_window.lut.h"
00128 #include "rendering/render_replaced.h"
00129 
00131 
00132 // table for screen object
00133 /*
00134 @begin ScreenTable 7
00135   height        Screen::Height      DontEnum|ReadOnly
00136   width         Screen::Width       DontEnum|ReadOnly
00137   colorDepth    Screen::ColorDepth  DontEnum|ReadOnly
00138   pixelDepth    Screen::PixelDepth  DontEnum|ReadOnly
00139   availLeft     Screen::AvailLeft   DontEnum|ReadOnly
00140   availTop      Screen::AvailTop    DontEnum|ReadOnly
00141   availHeight   Screen::AvailHeight DontEnum|ReadOnly
00142   availWidth    Screen::AvailWidth  DontEnum|ReadOnly
00143 @end
00144 */
00145 
00146 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
00147 
00148 // We set the object prototype so that toString is implemented
00149 Screen::Screen(ExecState *exec)
00150   : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
00151 
00152 Value Screen::get(ExecState *exec, const Identifier &p) const
00153 {
00154 #ifdef KJS_VERBOSE
00155   kdDebug(6070) << "Screen::get " << p.qstring() << endl;
00156 #endif
00157   return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
00158 }
00159 
00160 Value Screen::getValueProperty(ExecState *exec, int token) const
00161 {
00162 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00163   KWinModule info(0, KWinModule::INFO_DESKTOP);
00164 #endif
00165   QWidget *thisWidget = Window::retrieveActive(exec)->part()->widget();
00166   QRect sg = KGlobalSettings::desktopGeometry(thisWidget);
00167 
00168   switch( token ) {
00169   case Height:
00170     return Number(sg.height());
00171   case Width:
00172     return Number(sg.width());
00173   case ColorDepth:
00174   case PixelDepth: {
00175     QPaintDeviceMetrics m(QApplication::desktop());
00176     return Number(m.depth());
00177   }
00178   case AvailLeft: {
00179 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00180     QRect clipped = info.workArea().intersect(sg);
00181     return Number(clipped.x()-sg.x());
00182 #else
00183     return Number(10);
00184 #endif
00185   }
00186   case AvailTop: {
00187 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00188     QRect clipped = info.workArea().intersect(sg);
00189     return Number(clipped.y()-sg.y());
00190 #else
00191     return Number(10);
00192 #endif
00193   }
00194   case AvailHeight: {
00195 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00196     QRect clipped = info.workArea().intersect(sg);
00197     return Number(clipped.height());
00198 #else
00199     return Number(100);
00200 #endif
00201   }
00202   case AvailWidth: {
00203 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00204     QRect clipped = info.workArea().intersect(sg);
00205     return Number(clipped.width());
00206 #else
00207     return Number(100);
00208 #endif
00209   }
00210   default:
00211     kdDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token << endl;
00212     return Undefined();
00213   }
00214 }
00215 
00217 
00218 const ClassInfo Window::info = { "Window", &DOMAbstractView::info, &WindowTable, 0 };
00219 
00220 /*
00221 @begin WindowTable 89
00222   atob      Window::AToB        DontDelete|Function 1
00223   btoa      Window::BToA        DontDelete|Function 1
00224   closed    Window::Closed      DontDelete|ReadOnly
00225   crypto    Window::Crypto      DontDelete|ReadOnly
00226   defaultStatus Window::DefaultStatus   DontDelete
00227   defaultstatus Window::DefaultStatus   DontDelete
00228   status    Window::Status      DontDelete
00229   document  Window::Document    DontDelete|ReadOnly
00230   Node      Window::Node        DontDelete
00231   frameElement      Window::FrameElement        DontDelete|ReadOnly
00232   Event     Window::EventCtor   DontDelete
00233   Range     Window::Range       DontDelete
00234   NodeFilter    Window::NodeFilter  DontDelete
00235   DOMException  Window::DOMException    DontDelete
00236   CSSRule   Window::CSSRule     DontDelete
00237   frames    Window::Frames      DontDelete|ReadOnly
00238   history   Window::_History    DontDelete|ReadOnly
00239   external  Window::_External   DontDelete|ReadOnly
00240   event     Window::Event       DontDelete|ReadOnly
00241   innerHeight   Window::InnerHeight DontDelete|ReadOnly
00242   innerWidth    Window::InnerWidth  DontDelete|ReadOnly
00243   length    Window::Length      DontDelete|ReadOnly
00244   location  Window::_Location   DontDelete
00245   name      Window::Name        DontDelete
00246   navigator Window::_Navigator  DontDelete|ReadOnly
00247   clientInformation Window::ClientInformation   DontDelete|ReadOnly
00248   konqueror Window::_Konqueror  DontDelete|ReadOnly
00249   offscreenBuffering    Window::OffscreenBuffering  DontDelete|ReadOnly
00250   opener    Window::Opener      DontDelete|ReadOnly
00251   outerHeight   Window::OuterHeight DontDelete|ReadOnly
00252   outerWidth    Window::OuterWidth  DontDelete|ReadOnly
00253   pageXOffset   Window::PageXOffset DontDelete|ReadOnly
00254   pageYOffset   Window::PageYOffset DontDelete|ReadOnly
00255   parent    Window::Parent      DontDelete|ReadOnly
00256   personalbar   Window::Personalbar DontDelete|ReadOnly
00257   screenX   Window::ScreenX     DontDelete|ReadOnly
00258   screenY   Window::ScreenY     DontDelete|ReadOnly
00259   scrollbars    Window::Scrollbars  DontDelete|ReadOnly
00260   scroll    Window::Scroll      DontDelete|Function 2
00261   scrollBy  Window::ScrollBy    DontDelete|Function 2
00262   scrollTo  Window::ScrollTo    DontDelete|Function 2
00263   scrollX       Window::ScrollX         DontDelete|ReadOnly
00264   scrollY       Window::ScrollY         DontDelete|ReadOnly
00265   moveBy    Window::MoveBy      DontDelete|Function 2
00266   moveTo    Window::MoveTo      DontDelete|Function 2
00267   resizeBy  Window::ResizeBy    DontDelete|Function 2
00268   resizeTo  Window::ResizeTo    DontDelete|Function 2
00269   self      Window::Self        DontDelete|ReadOnly
00270   window    Window::_Window     DontDelete|ReadOnly
00271   top       Window::Top     DontDelete|ReadOnly
00272   screen    Window::_Screen     DontDelete|ReadOnly
00273   Image     Window::Image       DontDelete|ReadOnly
00274   Option    Window::Option      DontDelete|ReadOnly
00275   XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly
00276   XMLSerializer Window::XMLSerializer   DontDelete|ReadOnly
00277   DOMParser Window::DOMParser   DontDelete|ReadOnly
00278   alert     Window::Alert       DontDelete|Function 1
00279   confirm   Window::Confirm     DontDelete|Function 1
00280   prompt    Window::Prompt      DontDelete|Function 2
00281   open      Window::Open        DontDelete|Function 3
00282   setTimeout    Window::SetTimeout  DontDelete|Function 2
00283   clearTimeout  Window::ClearTimeout    DontDelete|Function 1
00284   focus     Window::Focus       DontDelete|Function 0
00285   blur      Window::Blur        DontDelete|Function 0
00286   close     Window::Close       DontDelete|Function 0
00287   setInterval   Window::SetInterval DontDelete|Function 2
00288   clearInterval Window::ClearInterval   DontDelete|Function 1
00289   captureEvents Window::CaptureEvents   DontDelete|Function 0
00290   releaseEvents Window::ReleaseEvents   DontDelete|Function 0
00291   print     Window::Print       DontDelete|Function 0
00292   addEventListener  Window::AddEventListener    DontDelete|Function 3
00293   removeEventListener   Window::RemoveEventListener DontDelete|Function 3
00294 # IE extension
00295   navigate  Window::Navigate    DontDelete|Function 1
00296 # Mozilla extension
00297   sidebar   Window::SideBar     DontDelete|ReadOnly
00298   getComputedStyle  Window::GetComputedStyle    DontDelete|Function 2
00299 
00300 # Warning, when adding a function to this object you need to add a case in Window::get
00301 
00302 # Event handlers
00303 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
00304 # ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll.
00305 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
00306   onabort   Window::Onabort     DontDelete
00307   onblur    Window::Onblur      DontDelete
00308   onchange  Window::Onchange    DontDelete
00309   onclick   Window::Onclick     DontDelete
00310   ondblclick    Window::Ondblclick  DontDelete
00311   ondragdrop    Window::Ondragdrop  DontDelete
00312   onerror   Window::Onerror     DontDelete
00313   onfocus   Window::Onfocus     DontDelete
00314   onkeydown Window::Onkeydown   DontDelete
00315   onkeypress    Window::Onkeypress  DontDelete
00316   onkeyup   Window::Onkeyup     DontDelete
00317   onload    Window::Onload      DontDelete
00318   onmousedown   Window::Onmousedown DontDelete
00319   onmousemove   Window::Onmousemove DontDelete
00320   onmouseout    Window::Onmouseout  DontDelete
00321   onmouseover   Window::Onmouseover DontDelete
00322   onmouseup Window::Onmouseup   DontDelete
00323   onmove    Window::Onmove      DontDelete
00324   onreset   Window::Onreset     DontDelete
00325   onresize  Window::Onresize    DontDelete
00326   onselect  Window::Onselect    DontDelete
00327   onsubmit  Window::Onsubmit    DontDelete
00328   onunload  Window::Onunload    DontDelete
00329 @end
00330 */
00331 IMPLEMENT_PROTOFUNC_DOM(WindowFunc)
00332 
00333 Window::Window(khtml::ChildFrame *p)
00334   : ObjectImp(/*no proto*/), m_frame(p), screen(0), history(0), external(0), m_frames(0), loc(0), m_evt(0)
00335 {
00336   winq = new WindowQObject(this);
00337   //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
00338 }
00339 
00340 Window::~Window()
00341 {
00342   delete winq;
00343 }
00344 
00345 Window *Window::retrieveWindow(KParts::ReadOnlyPart *p)
00346 {
00347   Object obj = Object::dynamicCast( retrieve( p ) );
00348 #ifndef NDEBUG
00349   // obj should never be null, except when javascript has been disabled in that part.
00350   KHTMLPart *part = ::qt_cast<KHTMLPart *>(p);
00351   if ( part && part->jScriptEnabled() )
00352   {
00353     assert( obj.isValid() );
00354 #ifndef QWS
00355     assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
00356 #endif
00357   }
00358 #endif
00359   if ( !obj.isValid() ) // JS disabled
00360     return 0;
00361   return static_cast<KJS::Window*>(obj.imp());
00362 }
00363 
00364 Window *Window::retrieveActive(ExecState *exec)
00365 {
00366   ValueImp *imp = exec->interpreter()->globalObject().imp();
00367   assert( imp );
00368 #ifndef QWS
00369   assert( dynamic_cast<KJS::Window*>(imp) );
00370 #endif
00371   return static_cast<KJS::Window*>(imp);
00372 }
00373 
00374 Value Window::retrieve(KParts::ReadOnlyPart *p)
00375 {
00376   assert(p);
00377   KHTMLPart * part = ::qt_cast<KHTMLPart *>(p);
00378   KJSProxy *proxy = 0L;
00379   if (!part) {
00380     part = ::qt_cast<KHTMLPart *>(p->parent());
00381     if (part)
00382       proxy = part->framejScript(p);
00383   } else
00384     proxy = part->jScript();
00385   if (proxy) {
00386 #ifdef KJS_VERBOSE
00387     kdDebug(6070) << "Window::retrieve part=" << part << " '" << part->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
00388 #endif
00389     return proxy->interpreter()->globalObject(); // the Global object is the "window"
00390   } else {
00391 #ifdef KJS_VERBOSE
00392     kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl;
00393 #endif
00394     return Undefined(); // This can happen with JS disabled on the domain of that window
00395   }
00396 }
00397 
00398 Location *Window::location() const
00399 {
00400   if (!loc)
00401     const_cast<Window*>(this)->loc = new Location(m_frame);
00402   return loc;
00403 }
00404 
00405 ObjectImp* Window::frames( ExecState* exec ) const
00406 {
00407   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00408   if (part)
00409     return m_frames ? m_frames :
00410       (const_cast<Window*>(this)->m_frames = new FrameArray(exec, part));
00411   return 0L;
00412 }
00413 
00414 // reference our special objects during garbage collection
00415 void Window::mark()
00416 {
00417   ObjectImp::mark();
00418   if (screen && !screen->marked())
00419     screen->mark();
00420   if (history && !history->marked())
00421     history->mark();
00422   if (external && !external->marked())
00423     external->mark();
00424   if (m_frames && !m_frames->marked())
00425     m_frames->mark();
00426   //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
00427   if (loc && !loc->marked())
00428     loc->mark();
00429   if (winq)
00430     winq->mark();
00431 }
00432 
00433 bool Window::hasProperty(ExecState *exec, const Identifier &p) const
00434 {
00435   // we don't want any operations on a closed window
00436   if (m_frame.isNull() || m_frame->m_part.isNull())
00437     return ( p == "closed" );
00438 
00439   if (ObjectImp::hasProperty(exec, p))
00440     return true;
00441 
00442   if (Lookup::findEntry(&WindowTable, p))
00443     return true;
00444 
00445   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00446   if (!part)
00447       return false;
00448 
00449   QString q = p.qstring();
00450   if (part->findFramePart(p.qstring()))
00451     return true;
00452   // allow window[1] or parent[1] etc. (#56983)
00453   bool ok;
00454   unsigned int i = p.toArrayIndex(&ok);
00455   if (ok) {
00456     QPtrList<KParts::ReadOnlyPart> frames = part->frames();
00457     unsigned int len = frames.count();
00458     if (i < len)
00459       return true;
00460   }
00461 
00462   // allow shortcuts like 'Image1' instead of document.images.Image1
00463   if (part->document().isHTMLDocument()) { // might be XML
00464     DOM::HTMLDocument doc = part->htmlDocument();
00465     // Keep in sync with tryGet
00466 
00467     if (static_cast<DOM::DocumentImpl*>(doc.handle())->underDocNamedCache().get(p.qstring()))
00468       return true;
00469 
00470     return !doc.getElementById(p.string()).isNull();
00471   }
00472 
00473   return false;
00474 }
00475 
00476 UString Window::toString(ExecState *) const
00477 {
00478   return "[object Window]";
00479 }
00480 
00481 Value Window::get(ExecState *exec, const Identifier &p) const
00482 {
00483 #ifdef KJS_VERBOSE
00484   kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
00485 #endif
00486   // we don't want any operations on a closed window
00487   if (m_frame.isNull() || m_frame->m_part.isNull()) {
00488     if ( p == "closed" )
00489       return Boolean( true );
00490     return Undefined();
00491   }
00492 
00493   // Look for overrides first
00494   ValueImp *val = getDirect(p);
00495   if (val) {
00496     //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
00497     return isSafeScript(exec) ? Value(val) : Undefined();
00498   }
00499 
00500   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
00501   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00502 
00503   // properties that work on all windows
00504   if (entry) {
00505     // ReadOnlyPart first
00506     switch(entry->value) {
00507     case Closed:
00508       return Boolean( false );
00509     case _Location:
00510         // No isSafeScript test here, we must be able to _set_ location.href (#49819)
00511       return Value(location());
00512     case _Window:
00513     case Self:
00514       return retrieve(m_frame->m_part);
00515     default:
00516         break;
00517     }
00518     if (!part)
00519         return Undefined();
00520     // KHTMLPart next
00521     switch(entry->value) {
00522     case Frames:
00523       return Value(frames(exec));
00524     case Opener:
00525       if (!part->opener())
00526         return Null();    // ### a null Window might be better, but == null
00527       else                // doesn't work yet
00528         return retrieve(part->opener());
00529     case Parent:
00530       return retrieve(part->parentPart() ? part->parentPart() : (KHTMLPart*)part);
00531     case Top: {
00532       KHTMLPart *p = part;
00533       while (p->parentPart())
00534         p = p->parentPart();
00535       return retrieve(p);
00536     }
00537     case Alert:
00538     case Confirm:
00539     case Prompt:
00540     case Open:
00541     case Close:
00542     case Focus:
00543     case Blur:
00544     case AToB:
00545     case BToA:
00546     case GetComputedStyle:
00547       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00548     default:
00549       break;
00550     }
00551   } else if (!part) {
00552     // not a  KHTMLPart
00553     QString rvalue;
00554     KParts::LiveConnectExtension::Type rtype;
00555     unsigned long robjid;
00556     if (m_frame->m_liveconnect &&
00557         isSafeScript(exec) &&
00558         m_frame->m_liveconnect->get(0, p.qstring(), rtype, robjid, rvalue))
00559       return getLiveConnectValue(m_frame->m_liveconnect, p.qstring(), rtype, rvalue, robjid);
00560     return Undefined();
00561   }
00562   // properties that only work on safe windows
00563   if (isSafeScript(exec) &&  entry)
00564   {
00565     //kdDebug(6070) << "token: " << entry->value << endl;
00566     switch( entry->value ) {
00567     case Crypto:
00568       return Undefined(); // ###
00569     case DefaultStatus:
00570       return String(UString(part->jsDefaultStatusBarText()));
00571     case Status:
00572       return String(UString(part->jsStatusBarText()));
00573     case Document:
00574       if (part->document().isNull()) {
00575         kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
00576         part->begin();
00577         part->write("<HTML><BODY>");
00578         part->end();
00579       }
00580       return getDOMNode(exec,part->document());
00581     case FrameElement:
00582       if (m_frame->m_frame)
00583         return getDOMNode(exec,m_frame->m_frame->element());
00584       else
00585         return Undefined();
00586     case Node:
00587       return getNodeConstructor(exec);
00588     case Range:
00589       return getRangeConstructor(exec);
00590     case NodeFilter:
00591       return getNodeFilterConstructor(exec);
00592     case DOMException:
00593       return getDOMExceptionConstructor(exec);
00594     case CSSRule:
00595       return getCSSRuleConstructor(exec);
00596     case EventCtor:
00597       return getEventConstructor(exec);
00598     case _History:
00599       return Value(history ? history :
00600                    (const_cast<Window*>(this)->history = new History(exec,part)));
00601 
00602     case _External:
00603       return Value(external ? external :
00604                    (const_cast<Window*>(this)->external = new External(exec,part)));
00605 
00606     case Event:
00607       if (m_evt)
00608         return getDOMEvent(exec,*m_evt);
00609       else {
00610 #ifdef KJS_VERBOSE
00611         kdDebug(6070) << "WARNING: window(" << this << "," << part->name() << ").event, no event!" << endl;
00612 #endif
00613         return Undefined();
00614       }
00615     case InnerHeight:
00616       if (!part->view())
00617         return Undefined();
00618       khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
00619       return Number(part->view()->visibleHeight());
00620     case InnerWidth:
00621       if (!part->view())
00622         return Undefined();
00623       khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
00624       return Number(part->view()->visibleWidth());
00625     case Length:
00626       return Number(part->frames().count());
00627     case Name:
00628       return String(part->name());
00629     case SideBar:
00630       return Value(new MozillaSidebarExtension(exec, part));
00631     case _Navigator:
00632     case ClientInformation: {
00633       // Store the navigator in the object so we get the same one each time.
00634       Value nav( new Navigator(exec, part) );
00635       const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
00636       const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
00637       return nav;
00638     }
00639 #ifdef Q_WS_QWS
00640     case _Konqueror: {
00641       Value k( new Konqueror(part) );
00642       const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal);
00643       return k;
00644     }
00645 #endif
00646     case OffscreenBuffering:
00647       return Boolean(true);
00648     case OuterHeight:
00649     case OuterWidth:
00650     {
00651 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00652       if (!part->widget())
00653         return Number(0);
00654       KWin::WindowInfo inf = KWin::windowInfo(part->widget()->topLevelWidget()->winId());
00655       return Number(entry->value == OuterHeight ?
00656                     inf.geometry().height() : inf.geometry().width());
00657 #else
00658       return Number(entry->value == OuterHeight ?  
00659             part->view()->height() : part->view()->width());
00660 #endif
00661     }
00662     case PageXOffset:
00663       return Number(part->view()->contentsX());
00664     case PageYOffset:
00665       return Number(part->view()->contentsY());
00666     case Personalbar:
00667       return Undefined(); // ###
00668     case ScreenLeft:
00669     case ScreenX: {
00670       if (!part->view())
00671         return Undefined();
00672       QRect sg = KGlobalSettings::desktopGeometry(part->view());
00673       return Number(part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
00674     }
00675     case ScreenTop:
00676     case ScreenY: {
00677       if (!part->view())
00678         return Undefined();
00679       QRect sg = KGlobalSettings::desktopGeometry(part->view());
00680       return Number(part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
00681     }
00682     case ScrollX: {
00683       if (!part->view())
00684         return Undefined();
00685       return Number(part->view()->contentsX());
00686     }
00687     case ScrollY: {
00688       if (!part->view())
00689         return Undefined();
00690       return Number(part->view()->contentsY());
00691     }
00692     case Scrollbars:
00693       return Undefined(); // ###
00694     case _Screen:
00695       return Value(screen ? screen :
00696                    (const_cast<Window*>(this)->screen = new Screen(exec)));
00697     case Image:
00698       return Value(new ImageConstructorImp(exec, part->document()));
00699     case Option:
00700       return Value(new OptionConstructorImp(exec, part->document()));
00701     case XMLHttpRequest:
00702       return Value(new XMLHttpRequestConstructorImp(exec, part->document()));
00703     case XMLSerializer:
00704       return Value(new XMLSerializerConstructorImp(exec));
00705     case DOMParser:
00706       return Value(new DOMParserConstructorImp(exec, part->xmlDocImpl()));
00707     case Scroll: // compatibility
00708     case ScrollBy:
00709     case ScrollTo:
00710     case MoveBy:
00711     case MoveTo:
00712     case ResizeBy:
00713     case ResizeTo:
00714     case CaptureEvents:
00715     case ReleaseEvents:
00716     case AddEventListener:
00717     case RemoveEventListener:
00718     case SetTimeout:
00719     case ClearTimeout:
00720     case SetInterval:
00721     case ClearInterval:
00722     case Print:
00723       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00724     // IE extension
00725     case Navigate:
00726       // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses
00727       // if (navigate) to test for IE (unlikely).
00728       if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
00729         return Undefined();
00730       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00731     case Onabort:
00732       return getListener(exec,DOM::EventImpl::ABORT_EVENT);
00733     case Onblur:
00734       return getListener(exec,DOM::EventImpl::BLUR_EVENT);
00735     case Onchange:
00736       return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
00737     case Onclick:
00738       return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
00739     case Ondblclick:
00740       return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
00741     case Ondragdrop:
00742       return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
00743     case Onerror:
00744       return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
00745     case Onfocus:
00746       return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
00747     case Onkeydown:
00748       return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
00749     case Onkeypress:
00750       return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
00751     case Onkeyup:
00752       return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
00753     case Onload:
00754       return getListener(exec,DOM::EventImpl::LOAD_EVENT);
00755     case Onmousedown:
00756       return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
00757     case Onmousemove:
00758       return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
00759     case Onmouseout:
00760       return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
00761     case Onmouseover:
00762       return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
00763     case Onmouseup:
00764       return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
00765     case Onmove:
00766       return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
00767     case Onreset:
00768       return getListener(exec,DOM::EventImpl::RESET_EVENT);
00769     case Onresize:
00770       return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
00771     case Onselect:
00772       return getListener(exec,DOM::EventImpl::SELECT_EVENT);
00773     case Onsubmit:
00774       return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
00775     case Onunload:
00776       return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
00777     }
00778   }
00779 
00780   // doing the remainder of ObjectImp::get() that is not covered by
00781   // the getDirect() call above.
00782   // #### guessed position. move further up or down?
00783   Object proto = Object::dynamicCast(prototype());
00784   assert(proto.isValid());
00785   if (p == specialPrototypePropertyName)
00786     return isSafeScript(exec) ? Value(proto) : Undefined();
00787   Value val2 = proto.get(exec, p);
00788   if (!val2.isA(UndefinedType)) {
00789     return isSafeScript(exec) ? val2 : Undefined();
00790   }
00791 
00792   KParts::ReadOnlyPart *rop = part->findFramePart( p.qstring() );
00793   if (rop)
00794     return retrieve(rop);
00795 
00796   // allow window[1] or parent[1] etc. (#56983)
00797   bool ok;
00798   unsigned int i = p.toArrayIndex(&ok);
00799   if (ok) {
00800     QPtrList<KParts::ReadOnlyPart> frames = part->frames();
00801     unsigned int len = frames.count();
00802     if (i < len) {
00803       KParts::ReadOnlyPart* frame = frames.at(i);
00804       if (frame)
00805         return Window::retrieve(frame);
00806     }
00807   }
00808 
00809   //Check for images, forms, objects, etc.
00810   if (isSafeScript(exec) && part->document().isHTMLDocument()) { // might be XML
00811     DOM::DocumentImpl* docImpl = part->xmlDocImpl();
00812     DOM::ElementMappingCache::ItemInfo* info = docImpl->underDocNamedCache().get(p.qstring());
00813     if (info) {
00814       //May be a false positive, but we can try to avoid doing it the hard way in
00815       //simpler cases. The trickiness here is that the cache is kept under both
00816       //name and id, but we sometimes ignore id for IE compat
00817       DOM::DOMString  propertyDOMString = p.string();
00818       if (info->nd && DOM::HTMLMappedNameCollectionImpl::matchesName(info->nd,
00819                     DOM::HTMLCollectionImpl::WINDOW_NAMED_ITEMS, propertyDOMString)) {
00820         return getDOMNode(exec, info->nd);
00821       } else {
00822         //Can't tell it just like that, so better go through collection and count stuff. This is the slow path...
00823         DOM::HTMLMappedNameCollection coll(docImpl, DOM::HTMLCollectionImpl::WINDOW_NAMED_ITEMS, propertyDOMString);
00824   
00825         if (coll.length() == 1)
00826           return getDOMNode(exec, coll.firstItem());
00827         else if (coll.length() > 1)
00828           return getHTMLCollection(exec, coll);
00829       }
00830     }
00831     DOM::Element element = part->document().getElementById(p.string());
00832     if ( !element.isNull() )
00833       return getDOMNode(exec, element );
00834   }
00835 
00836   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
00837   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
00838 #ifdef KJS_VERBOSE
00839   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
00840 #endif
00841   return Undefined();
00842 }
00843 
00844 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
00845 {
00846   // we don't want any operations on a closed window
00847   if (m_frame.isNull() || m_frame->m_part.isNull()) {
00848     // ### throw exception? allow setting of some props like location?
00849     return;
00850   }
00851 
00852   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
00853   // If yes, save time and jump directly to ObjectImp.
00854   if ( (attr != None && attr != DontDelete) ||
00855        // Same thing if we have a local override (e.g. "var location")
00856        ( isSafeScript( exec ) && ObjectImp::getDirect(propertyName) ) )
00857   {
00858     ObjectImp::put( exec, propertyName, value, attr );
00859     return;
00860   }
00861 
00862   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
00863   if (entry && !m_frame.isNull() && !m_frame->m_part.isNull())
00864   {
00865 #ifdef KJS_VERBOSE
00866     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
00867 #endif
00868     switch( entry->value) {
00869     case _Location:
00870       goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/);
00871       return;
00872     default:
00873       break;
00874     }
00875     KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
00876     if (part) {
00877     switch( entry->value ) {
00878     case Status: {
00879       if  (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
00880         == KHTMLSettings::KJSWindowStatusAllow) {
00881       String s = value.toString(exec);
00882       part->setJSStatusBarText(s.value().qstring());
00883       }
00884       return;
00885     }
00886     case DefaultStatus: {
00887       if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
00888         == KHTMLSettings::KJSWindowStatusAllow) {
00889       String s = value.toString(exec);
00890       part->setJSDefaultStatusBarText(s.value().qstring());
00891       }
00892       return;
00893     }
00894     case Onabort:
00895       if (isSafeScript(exec))
00896         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
00897       return;
00898     case Onblur:
00899       if (isSafeScript(exec))
00900         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
00901       return;
00902     case Onchange:
00903       if (isSafeScript(exec))
00904         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
00905       return;
00906     case Onclick:
00907       if (isSafeScript(exec))
00908         setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
00909       return;
00910     case Ondblclick:
00911       if (isSafeScript(exec))
00912         setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
00913       return;
00914     case Ondragdrop:
00915       if (isSafeScript(exec))
00916         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
00917       return;
00918     case Onerror:
00919       if (isSafeScript(exec))
00920         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
00921       return;
00922     case Onfocus:
00923       if (isSafeScript(exec))
00924         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
00925       return;
00926     case Onkeydown:
00927       if (isSafeScript(exec))
00928         setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
00929       return;
00930     case Onkeypress:
00931       if (isSafeScript(exec))
00932         setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
00933       return;
00934     case Onkeyup:
00935       if (isSafeScript(exec))
00936         setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
00937       return;
00938     case Onload:
00939       if (isSafeScript(exec))
00940         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
00941       return;
00942     case Onmousedown:
00943       if (isSafeScript(exec))
00944         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
00945       return;
00946     case Onmousemove:
00947       if (isSafeScript(exec))
00948         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
00949       return;
00950     case Onmouseout:
00951       if (isSafeScript(exec))
00952         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
00953       return;
00954     case Onmouseover:
00955       if (isSafeScript(exec))
00956         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
00957       return;
00958     case Onmouseup:
00959       if (isSafeScript(exec))
00960         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
00961       return;
00962     case Onmove:
00963       if (isSafeScript(exec))
00964         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
00965       return;
00966     case Onreset:
00967       if (isSafeScript(exec))
00968         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
00969       return;
00970     case Onresize:
00971       if (isSafeScript(exec))
00972         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
00973       return;
00974     case Onselect:
00975       if (isSafeScript(exec))
00976         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
00977       return;
00978     case Onsubmit:
00979       if (isSafeScript(exec))
00980         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
00981       return;
00982     case Onunload:
00983       if (isSafeScript(exec))
00984         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
00985       return;
00986     case Name:
00987       if (isSafeScript(exec))
00988         part->setName( value.toString(exec).qstring().local8Bit().data() );
00989       return;
00990     default:
00991       break;
00992     }
00993     }
00994   }
00995   if (m_frame->m_liveconnect &&
00996       isSafeScript(exec) &&
00997       m_frame->m_liveconnect->put(0, propertyName.qstring(), value.toString(exec).qstring()))
00998     return;
00999   if (isSafeScript(exec)) {
01000     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
01001     ObjectImp::put(exec, propertyName, value, attr);
01002   }
01003 }
01004 
01005 bool Window::toBoolean(ExecState *) const
01006 {
01007   return !m_frame.isNull() && !m_frame->m_part.isNull();
01008 }
01009 
01010 DOM::AbstractView Window::toAbstractView() const
01011 {
01012   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01013   if (!part)
01014     return DOM::AbstractView();
01015   return part->document().defaultView();
01016 }
01017 
01018 void Window::scheduleClose()
01019 {
01020   kdDebug(6070) << "Window::scheduleClose window.close() " << m_frame << endl;
01021   Q_ASSERT(winq);
01022   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
01023 }
01024 
01025 void Window::closeNow()
01026 {
01027   if (m_frame.isNull() || m_frame->m_part.isNull()) {
01028     kdDebug(6070) << k_funcinfo << "part is deleted already" << endl;
01029   } else {
01030     KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01031     if (!part) {
01032       kdDebug(6070) << "closeNow on non KHTML part" << endl;
01033     } else {
01034       //kdDebug(6070) << k_funcinfo << " -> closing window" << endl;
01035       // We want to make sure that window.open won't find this part by name.
01036       part->setName( 0 );
01037       part->deleteLater();
01038       part = 0;
01039     }
01040   }
01041 }
01042 
01043 void Window::afterScriptExecution()
01044 {
01045   DOM::DocumentImpl::updateDocumentsRendering();
01046   QValueList<DelayedAction> delayedActions = m_delayed;
01047   m_delayed.clear();
01048   QValueList<DelayedAction>::Iterator it = delayedActions.begin();
01049   for ( ; it != delayedActions.end() ; ++it )
01050   {
01051     switch ((*it).actionId) {
01052     case DelayedClose:
01053       scheduleClose();
01054       return; // stop here, in case of multiple actions
01055     case DelayedGoHistory:
01056       goHistory( (*it).param.toInt() );
01057       break;
01058     case NullAction:
01059       // FIXME: anything needs to be done here?  This is warning anyways.
01060       break;
01061     };
01062   }
01063 }
01064 
01065 bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const
01066 {
01067   if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access
01068     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
01069     return false;
01070   }
01071   if (!activePart) {
01072     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
01073     return false;
01074   }
01075    if ( activePart == m_frame->m_part ) // Not calling from another frame, no problem.
01076      return true;
01077 
01078   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01079   if (!part)
01080     return true; // not a KHTMLPart
01081 
01082   if ( part->document().isNull() )
01083     return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
01084 
01085   DOM::HTMLDocument thisDocument = part->htmlDocument();
01086   if ( thisDocument.isNull() ) {
01087     kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl;
01088     return false;
01089   }
01090 
01091   KHTMLPart *activeKHTMLPart = ::qt_cast<KHTMLPart *>(activePart);
01092   if (!activeKHTMLPart)
01093     return true; // not a KHTMLPart
01094 
01095   DOM::HTMLDocument actDocument = activeKHTMLPart->htmlDocument();
01096   if ( actDocument.isNull() ) {
01097     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
01098     return false;
01099   }
01100   DOM::DOMString actDomain = actDocument.domain();
01101   DOM::DOMString thisDomain = thisDocument.domain();
01102 
01103   if ( actDomain == thisDomain ) {
01104 #ifdef KJS_VERBOSE
01105     //kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl;
01106 #endif
01107     return true;
01108   }
01109 
01110   kdDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
01111   // TODO after 3.1: throw security exception (exec->setException())
01112   return false;
01113 }
01114 
01115 void Window::setListener(ExecState *exec, int eventId, Value func)
01116 {
01117   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01118   if (!part || !isSafeScript(exec))
01119     return;
01120   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
01121   if (!doc)
01122     return;
01123 
01124   doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
01125 }
01126 
01127 Value Window::getListener(ExecState *exec, int eventId) const
01128 {
01129   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01130   if (!part || !isSafeScript(exec))
01131     return Undefined();
01132   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
01133   if (!doc)
01134     return Undefined();
01135 
01136   DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
01137   if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
01138     return static_cast<JSEventListener*>(listener)->listenerObj();
01139   else
01140     return Null();
01141 }
01142 
01143 
01144 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
01145 {
01146   // This function is so hot that it's worth coding it directly with imps.
01147   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01148   if (!part || val.type() != ObjectType)
01149     return 0;
01150 
01151   // It's ObjectType, so it must be valid.
01152   Object listenerObject = Object::dynamicCast(val);
01153   ObjectImp *listenerObjectImp = listenerObject.imp();
01154 
01155   // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!)
01156   if (!listenerObject.implementsCall() && part && part->jScript() && part->jScript()->interpreter())
01157   {
01158     Interpreter *interpreter = part->jScript()->interpreter();
01159 
01160     // 'listener' probably is an EventListener object containing a 'handleEvent' function.
01161     Value handleEventValue = listenerObject.get(interpreter->globalExec(), Identifier("handleEvent"));
01162     Object handleEventObject = Object::dynamicCast(handleEventValue);
01163 
01164     if(handleEventObject.isValid() && handleEventObject.implementsCall())
01165     {
01166       listenerObject = handleEventObject;
01167       listenerObjectImp = handleEventObject.imp();
01168     }
01169   }
01170 
01171   JSEventListener *existingListener = jsEventListeners[listenerObjectImp];
01172   if (existingListener) {
01173      if ( existingListener->isHTMLEventListener() != html )
01174         // The existingListener will have the wrong type, so onclick= will behave like addEventListener or vice versa.
01175         kdWarning() << "getJSEventListener: event listener already found but with html=" << !html << " - please report this, we thought it would never happen" << endl;
01176     return existingListener;
01177   }
01178 
01179   // Note that the JSEventListener constructor adds it to our jsEventListeners list
01180   return new JSEventListener(listenerObject, listenerObjectImp, Object(this), html);
01181 }
01182 
01183 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, const QString& name, DOM::NodeImpl *node)
01184 {
01185   return new JSLazyEventListener(code, name, Object(this), node);
01186 }
01187 
01188 void Window::clear( ExecState *exec )
01189 {
01190   delete winq;
01191   winq = 0L;
01192   // Get rid of everything, those user vars could hold references to DOM nodes
01193   deleteAllProperties( exec );
01194 
01195   // Break the dependency between the listeners and their object
01196   QPtrDictIterator<JSEventListener> it(jsEventListeners);
01197   for (; it.current(); ++it)
01198     it.current()->clear();
01199   // Forget about the listeners (the DOM::NodeImpls will delete them)
01200   jsEventListeners.clear();
01201 
01202   if (m_frame) {
01203     KJSProxy* proxy = m_frame->m_jscript;
01204     if (proxy) // i.e. JS not disabled
01205     {
01206       winq = new WindowQObject(this);
01207       // Now recreate a working global object for the next URL that will use us
01208       KJS::Interpreter *interpreter = proxy->interpreter();
01209       interpreter->initGlobalObject();
01210     }
01211   }
01212 }
01213 
01214 void Window::setCurrentEvent( DOM::Event *evt )
01215 {
01216   m_evt = evt;
01217   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
01218 }
01219 
01220 void Window::goURL(ExecState* exec, const QString& url, bool lockHistory)
01221 {
01222   Window* active = Window::retrieveActive(exec);
01223   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01224   KHTMLPart *active_part = ::qt_cast<KHTMLPart *>(active->part());
01225   // Complete the URL using the "active part" (running interpreter)
01226   if (active_part && part) {
01227     if (url[0] == QChar('#')) {
01228       part->gotoAnchor(url.mid(1));
01229     } else {
01230       QString dstUrl = active_part->htmlDocument().completeURL(url).string();
01231       kdDebug(6070) << "Window::goURL dstUrl=" << dstUrl << endl;
01232 
01233       // check if we're allowed to inject javascript
01234       // SYNC check with khtml_part.cpp::slotRedirect!
01235       if ( isSafeScript(exec) ||
01236             dstUrl.find(QString::fromLatin1("javascript:"), 0, false) != 0 )
01237         part->scheduleRedirection(-1,
01238                                   dstUrl,
01239                                   lockHistory);
01240     }
01241   } else if (!part && !m_frame->m_part.isNull()) {
01242     KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part);
01243     if (b)
01244       b->emit openURLRequest(m_frame->m_frame->element()->getDocument()->completeURL(url));
01245     kdDebug() << "goURL for ROPart" << endl;
01246   }
01247 }
01248 
01249 KParts::ReadOnlyPart *Window::part() const {
01250     return m_frame.isNull() ? 0L : static_cast<KParts::ReadOnlyPart *>(m_frame->m_part);
01251 }
01252 
01253 void Window::delayedGoHistory( int steps )
01254 {
01255     m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
01256 }
01257 
01258 void Window::goHistory( int steps )
01259 {
01260   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01261   if(!part)
01262       // TODO history readonlypart
01263     return;
01264   KParts::BrowserExtension *ext = part->browserExtension();
01265   if(!ext)
01266     return;
01267   KParts::BrowserInterface *iface = ext->browserInterface();
01268 
01269   if ( !iface )
01270     return;
01271 
01272   iface->callMethod( "goHistory(int)", steps );
01273   //emit ext->goHistory(steps);
01274 }
01275 
01276 void KJS::Window::resizeTo(QWidget* tl, int width, int height)
01277 {
01278   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01279   if(!part)
01280       // TODO resizeTo readonlypart
01281     return;
01282   KParts::BrowserExtension *ext = part->browserExtension();
01283   if (!ext) {
01284     kdDebug(6070) << "Window::resizeTo found no browserExtension" << endl;
01285     return;
01286   }
01287 
01288   // Security check: within desktop limits and bigger than 100x100 (per spec)
01289   if ( width < 100 || height < 100 ) {
01290     kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl;
01291     return;
01292   }
01293 
01294   QRect sg = KGlobalSettings::desktopGeometry(tl);
01295 
01296   if ( width > sg.width() || height > sg.height() ) {
01297     kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl;
01298     return;
01299   }
01300 
01301   kdDebug(6070) << "resizing to " << width << "x" << height << endl;
01302 
01303   emit ext->resizeTopLevelWidget( width, height );
01304 
01305   // If the window is out of the desktop, move it up/left
01306   // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
01307   int right = tl->x() + tl->frameGeometry().width();
01308   int bottom = tl->y() + tl->frameGeometry().height();
01309   int moveByX = 0;
01310   int moveByY = 0;
01311   if ( right > sg.right() )
01312     moveByX = - right + sg.right(); // always <0
01313   if ( bottom > sg.bottom() )
01314     moveByY = - bottom + sg.bottom(); // always <0
01315   if ( moveByX || moveByY )
01316     emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY );
01317 }
01318 
01319 Value Window::openWindow(ExecState *exec, const List& args)
01320 {
01321   KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01322   if (!part)
01323     return Undefined();
01324   KHTMLView *widget = part->view();
01325   Value v = args[0];
01326   QString str = v.toString(exec).qstring();
01327 
01328   // prepare arguments
01329   KURL url;
01330   if (!str.isEmpty())
01331   {
01332     KHTMLPart* p = ::qt_cast<KHTMLPart *>(Window::retrieveActive(exec)->m_frame->m_part);
01333     if ( p )
01334       url = p->htmlDocument().completeURL(str).string();
01335     if ( !p ||
01336          !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
01337       return Undefined();
01338   }
01339 
01340   KHTMLSettings::KJSWindowOpenPolicy policy =
01341         part->settings()->windowOpenPolicy(part->url().host());
01342   if ( policy == KHTMLSettings::KJSWindowOpenAsk ) {
01343     emit part->browserExtension()->requestFocus(part);
01344     QString caption;
01345     if (!part->url().host().isEmpty())
01346       caption = part->url().host() + " - ";
01347     caption += i18n( "Confirmation: JavaScript Popup" );
01348     if ( KMessageBox::questionYesNo(widget,
01349                                     str.isEmpty() ?
01350                                     i18n( "This site is requesting to open up a new browser "
01351                                           "window via JavaScript.\n"
01352                                           "Do you want to allow this?" ) :
01353                                     i18n( "<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />"
01354                                           "Do you want to allow this?</qt>").arg(KStringHandler::csqueeze(url.htmlURL(),  100)),
01355                                     caption, i18n("Allow"), i18n("Do Not Allow") ) == KMessageBox::Yes )
01356       policy = KHTMLSettings::KJSWindowOpenAllow;
01357   } else if ( policy == KHTMLSettings::KJSWindowOpenSmart )
01358   {
01359     // window.open disabled unless from a key/mouse event
01360     if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed())
01361       policy = KHTMLSettings::KJSWindowOpenAllow;
01362   }
01363 
01364   QString frameName = args.size() > 1 ? args[1].toString(exec).qstring() : QString("_blank");
01365 
01366   v = args[2];
01367   QString features;
01368   if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
01369     features = v.toString(exec).qstring();
01370     // Buggy scripts have ' at beginning and end, cut those
01371     if (features.startsWith("\'") && features.endsWith("\'"))
01372       features = features.mid(1, features.length()-2);
01373   }
01374 
01375   if ( policy != KHTMLSettings::KJSWindowOpenAllow ) {
01376     if ( url.isEmpty() )
01377       part->setSuppressedPopupIndicator(true, 0);
01378     else {
01379       part->setSuppressedPopupIndicator(true, part);
01380       m_suppressedWindowInfo.append( SuppressedWindowInfo( exec, url, frameName, features ) );
01381     }
01382     return Undefined();
01383   } else {
01384     return executeOpenWindow(exec, url, frameName, features);
01385   }
01386 }
01387 
01388 Value Window::executeOpenWindow(ExecState *exec, const KURL& url, const QString& frameName, const QString& features)
01389 {
01390     KHTMLPart *p = ::qt_cast<KHTMLPart *>(m_frame->m_part);
01391     KHTMLView *widget = p->view();
01392     KParts::WindowArgs winargs;
01393 
01394     // scan feature argument
01395     if (!features.isEmpty()) {
01396       // specifying window params means false defaults
01397       winargs.menuBarVisible = false;
01398       winargs.toolBarsVisible = false;
01399       winargs.statusBarVisible = false;
01400       winargs.scrollBarsVisible = false;
01401       QStringList flist = QStringList::split(',', features);
01402       QStringList::ConstIterator it = flist.begin();
01403       while (it != flist.end()) {
01404         QString s = *it++;
01405         QString key, val;
01406         int pos = s.find('=');
01407         if (pos >= 0) {
01408           key = s.left(pos).stripWhiteSpace().lower();
01409           val = s.mid(pos + 1).stripWhiteSpace().lower();
01410           QRect screen = KGlobalSettings::desktopGeometry(widget->topLevelWidget());
01411 
01412           if (key == "left" || key == "screenx") {
01413             winargs.x = (int)val.toFloat() + screen.x();
01414             if (winargs.x < screen.x() || winargs.x > screen.right())
01415               winargs.x = screen.x(); // only safe choice until size is determined
01416           } else if (key == "top" || key == "screeny") {
01417             winargs.y = (int)val.toFloat() + screen.y();
01418             if (winargs.y < screen.y() || winargs.y > screen.bottom())
01419               winargs.y = screen.y(); // only safe choice until size is determined
01420           } else if (key == "height") {
01421             winargs.height = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01422             if (winargs.height > screen.height())  // should actually check workspace
01423               winargs.height = screen.height();
01424             if (winargs.height < 100)
01425               winargs.height = 100;
01426           } else if (key == "width") {
01427             winargs.width = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01428             if (winargs.width > screen.width())    // should actually check workspace
01429               winargs.width = screen.width();
01430             if (winargs.width < 100)
01431               winargs.width = 100;
01432           } else {
01433             goto boolargs;
01434           }
01435           continue;
01436         } else {
01437           // leaving away the value gives true
01438           key = s.stripWhiteSpace().lower();
01439           val = "1";
01440         }
01441       boolargs:
01442         if (key == "menubar")
01443           winargs.menuBarVisible = (val == "1" || val == "yes");
01444         else if (key == "toolbar")
01445           winargs.toolBarsVisible = (val == "1" || val == "yes");
01446         else if (key == "location")  // ### missing in WindowArgs
01447           winargs.toolBarsVisible = (val == "1" || val == "yes");
01448         else if (key == "status" || key == "statusbar")
01449           winargs.statusBarVisible = (val == "1" || val == "yes");
01450         else if (key == "scrollbars")
01451           winargs.scrollBarsVisible = (val == "1" || val == "yes");
01452         else if (key == "resizable")
01453           winargs.resizable = (val == "1" || val == "yes");
01454         else if (key == "fullscreen")
01455           winargs.fullscreen = (val == "1" || val == "yes");
01456       }
01457     }
01458 
01459     KParts::URLArgs uargs;
01460     uargs.frameName = frameName;
01461 
01462     if ( uargs.frameName.lower() == "_top" )
01463     {
01464       while ( p->parentPart() )
01465         p = p->parentPart();
01466       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01467       return Window::retrieve(p);
01468     }
01469     if ( uargs.frameName.lower() == "_parent" )
01470     {
01471       if ( p->parentPart() )
01472         p = p->parentPart();
01473       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01474       return Window::retrieve(p);
01475     }
01476     if ( uargs.frameName.lower() == "_self")
01477     {
01478       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01479       return Window::retrieve(p);
01480     }
01481     if ( uargs.frameName.lower() == "replace" )
01482     {
01483       Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/);
01484       return Window::retrieve(p);
01485     }
01486     uargs.serviceType = "text/html";
01487 
01488     // request window (new or existing if framename is set)
01489     KParts::ReadOnlyPart *newPart = 0L;
01490     emit p->browserExtension()->createNewWindow(KURL(), uargs,winargs,newPart);
01491     if (newPart && ::qt_cast<KHTMLPart*>(newPart)) {
01492       KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
01493       //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
01494       khtmlpart->setOpener(p);
01495       khtmlpart->setOpenedByJS(true);
01496       if (khtmlpart->document().isNull()) {
01497         khtmlpart->begin();
01498         khtmlpart->write("<HTML><BODY>");
01499         khtmlpart->end();
01500         if ( p->docImpl() ) {
01501           //kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
01502           khtmlpart->docImpl()->setDomain( p->docImpl()->domain());
01503           khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
01504         }
01505       }
01506       uargs.serviceType = QString::null;
01507       if (uargs.frameName.lower() == "_blank")
01508         uargs.frameName = QString::null;
01509       if (!url.isEmpty())
01510         emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
01511       return Window::retrieve(khtmlpart); // global object
01512     } else
01513       return Undefined();
01514 }
01515 
01516 void Window::forgetSuppressedWindows()
01517 {
01518   m_suppressedWindowInfo.clear();
01519 }
01520 
01521 void Window::showSuppressedWindows()
01522 {
01523   QValueList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo;
01524   m_suppressedWindowInfo.clear();
01525   QValueList<SuppressedWindowInfo>::Iterator it = suppressedWindowInfo.begin();
01526   for ( ; it != suppressedWindowInfo.end() ; ++it ) {
01527     executeOpenWindow((*it).exec, (*it).url, (*it).frameName, (*it).features);
01528   }
01529 }
01530 
01531 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01532 {
01533   KJS_CHECK_THIS( Window, thisObj );
01534   Window *window = static_cast<Window *>(thisObj.imp());
01535   QString str, str2;
01536 
01537   KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
01538   if (!part)
01539     return Undefined();
01540 
01541   KHTMLView *widget = part->view();
01542   Value v = args[0];
01543   UString s = v.toString(exec);
01544   str = s.qstring();
01545 
01546   QString caption;
01547   if (part && !part->url().host().isEmpty())
01548     caption = part->url().host() + " - ";
01549   caption += "JavaScript"; // TODO: i18n
01550   // functions that work everywhere
01551   switch(id) {
01552   case Window::Alert:
01553     if (!widget->dialogsAllowed())
01554       return Undefined();
01555     if ( part && part->xmlDocImpl() )
01556       part->xmlDocImpl()->updateRendering();
01557     if ( part )
01558       emit part->browserExtension()->requestFocus(part);
01559     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), caption);
01560     return Undefined();
01561   case Window::Confirm:
01562     if (!widget->dialogsAllowed())
01563       return Undefined();
01564     if ( part && part->xmlDocImpl() )
01565       part->xmlDocImpl()->updateRendering();
01566     if ( part )
01567       emit part->browserExtension()->requestFocus(part);
01568     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), caption,
01569                                                 KStdGuiItem::ok(), KStdGuiItem::cancel()) == KMessageBox::Yes));
01570   case Window::Prompt:
01571 #ifndef KONQ_EMBEDDED
01572     if (!widget->dialogsAllowed())
01573       return Undefined();
01574     if ( part && part->xmlDocImpl() )
01575       part->xmlDocImpl()->updateRendering();
01576     if ( part )
01577       emit part->browserExtension()->requestFocus(part);
01578     bool ok;
01579     if (args.size() >= 2)
01580       str2 = KInputDialog::getText(caption,
01581                                    QStyleSheet::convertFromPlainText(str),
01582                                    args[1].toString(exec).qstring(), &ok, widget);
01583     else
01584       str2 = KInputDialog::getText(caption,
01585                                    QStyleSheet::convertFromPlainText(str),
01586                                    QString::null, &ok, widget);
01587     if ( ok )
01588         return String(str2);
01589     else
01590         return Null();
01591 #else
01592     return Undefined();
01593 #endif
01594   case Window::GetComputedStyle:  {
01595        if ( !part || !part->xmlDocImpl() )
01596          return Undefined();
01597         DOM::Node arg0 = toNode(args[0]);
01598         if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
01599           return Undefined(); // throw exception?
01600         else
01601           return getDOMCSSStyleDeclaration(exec, part->document().defaultView().getComputedStyle(static_cast<DOM::Element>(arg0),
01602                                                                               args[1].toString(exec).string()));
01603       }
01604   case Window::Open:
01605     return window->openWindow(exec, args);
01606   case Window::Close: {
01607     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
01608        The close method closes only windows opened by JavaScript using the open method.
01609        If you attempt to close any other window, a confirm is generated, which
01610        lets the user choose whether the window closes.
01611        This is a security feature to prevent "mail bombs" containing self.close().
01612        However, if the window has only one document (the current one) in its
01613        session history, the close is allowed without any confirm. This is a
01614        special case for one-off windows that need to open other windows and
01615        then dispose of themselves.
01616     */
01617     bool doClose = false;
01618     if (!part->openedByJS())
01619     {
01620       // To conform to the SPEC, we only ask if the window
01621       // has more than one entry in the history (NS does that too).
01622       History history(exec,part);
01623 
01624       if ( history.get( exec, "length" ).toInt32(exec) <= 1 )
01625       {
01626         doClose = true;
01627       }
01628       else
01629       {
01630         // Can we get this dialog with tabs??? Does it close the window or the tab in that case?
01631         emit part->browserExtension()->requestFocus(part);
01632         if ( KMessageBox::questionYesNo( window->part()->widget(),
01633                                          i18n("Close window?"), i18n("Confirmation Required"),
01634                                          KStdGuiItem::close(), KStdGuiItem::cancel() )
01635              == KMessageBox::Yes )
01636           doClose = true;
01637       }
01638     }
01639     else
01640       doClose = true;
01641 
01642     if (doClose)
01643     {
01644       // If this is the current window (the one the interpreter runs in),
01645       // then schedule a delayed close (so that the script terminates first).
01646       // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
01647       if ( Window::retrieveActive(exec) == window ) {
01648         if (widget) {
01649           // quit all dialogs of this view
01650           // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
01651           widget->closeChildDialogs();
01652         }
01653         //kdDebug() << "scheduling delayed close"  << endl;
01654         // We'll close the window at the end of the script execution
01655         Window* w = const_cast<Window*>(window);
01656         w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
01657       } else {
01658         //kdDebug() << "closing NOW"  << endl;
01659         (const_cast<Window*>(window))->closeNow();
01660       }
01661     }
01662     return Undefined();
01663   }
01664   case Window::Navigate:
01665     window->goURL(exec, args[0].toString(exec).qstring(), false /*don't lock history*/);
01666     return Undefined();
01667   case Window::Focus: {
01668     KHTMLSettings::KJSWindowFocusPolicy policy =
01669         part->settings()->windowFocusPolicy(part->url().host());
01670     if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) {
01671       widget->topLevelWidget()->raise();
01672       KWin::deIconifyWindow( widget->topLevelWidget()->winId() );
01673       widget->setActiveWindow();
01674       emit part->browserExtension()->requestFocus(part);
01675     }
01676     return Undefined();
01677   }
01678   case Window::Blur:
01679     // TODO
01680     return Undefined();
01681   case Window::BToA:
01682   case Window::AToB: {
01683       if (!s.is8Bit())
01684           return Undefined();
01685        QByteArray  in, out;
01686        char *binData = s.ascii();
01687        in.setRawData( binData, s.size() );
01688        if (id == Window::AToB)
01689            KCodecs::base64Decode( in, out );
01690        else
01691            KCodecs::base64Encode( in, out );
01692        in.resetRawData( binData, s.size() );
01693        UChar *d = new UChar[out.size()];
01694        for (uint i = 0; i < out.size(); i++)
01695            d[i].uc = (uchar) out[i];
01696        UString ret(d, out.size(), false /*no copy*/);
01697        return String(ret);
01698   }
01699 
01700   };
01701 
01702 
01703   // now unsafe functions..
01704   if (!window->isSafeScript(exec))
01705     return Undefined();
01706 
01707   switch (id) {
01708   case Window::ScrollBy:
01709     if(args.size() == 2 && widget)
01710       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
01711     return Undefined();
01712   case Window::Scroll:
01713   case Window::ScrollTo:
01714     if(args.size() == 2 && widget)
01715       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
01716     return Undefined();
01717   case Window::MoveBy: {
01718     KHTMLSettings::KJSWindowMovePolicy policy =
01719         part->settings()->windowMovePolicy(part->url().host());
01720     if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
01721     {
01722       KParts::BrowserExtension *ext = part->browserExtension();
01723       if (ext) {
01724         QWidget * tl = widget->topLevelWidget();
01725         QRect sg = KGlobalSettings::desktopGeometry(tl);
01726 
01727         QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
01728         // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01729         if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
01730              dest.x()+tl->width() <= sg.width()+sg.x() &&
01731              dest.y()+tl->height() <= sg.height()+sg.y() )
01732           emit ext->moveTopLevelWidget( dest.x(), dest.y() );
01733       }
01734     }
01735     return Undefined();
01736   }
01737   case Window::MoveTo: {
01738     KHTMLSettings::KJSWindowMovePolicy policy =
01739         part->settings()->windowMovePolicy(part->url().host());
01740     if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
01741     {
01742       KParts::BrowserExtension *ext = part->browserExtension();
01743       if (ext) {
01744         QWidget * tl = widget->topLevelWidget();
01745         QRect sg = KGlobalSettings::desktopGeometry(tl);
01746 
01747         QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
01748         // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01749         if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
01750              dest.x()+tl->width() <= sg.width()+sg.x() &&
01751              dest.y()+tl->height() <= sg.height()+sg.y() )
01752         emit ext->moveTopLevelWidget( dest.x(), dest.y() );
01753       }
01754     }
01755     return Undefined();
01756   }
01757   case Window::ResizeBy: {
01758     KHTMLSettings::KJSWindowResizePolicy policy =
01759         part->settings()->windowResizePolicy(part->url().host());
01760     if(policy == KHTMLSettings::KJSWindowResizeAllow
01761             && args.size() == 2 && widget)
01762     {
01763       QWidget * tl = widget->topLevelWidget();
01764       QRect geom = tl->frameGeometry();
01765       window->resizeTo( tl,
01766                         geom.width() + args[0].toInt32(exec),
01767                         geom.height() + args[1].toInt32(exec) );
01768     }
01769     return Undefined();
01770   }
01771   case Window::ResizeTo: {
01772     KHTMLSettings::KJSWindowResizePolicy policy =
01773                part->settings()->windowResizePolicy(part->url().host());
01774     if(policy == KHTMLSettings::KJSWindowResizeAllow
01775                && args.size() == 2 && widget)
01776     {
01777       QWidget * tl = widget->topLevelWidget();
01778       window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
01779     }
01780     return Undefined();
01781   }
01782   case Window::SetTimeout:
01783   case Window::SetInterval: {
01784     bool singleShot;
01785     int i; // timeout interval
01786     if (args.size() == 0)
01787       return Undefined();
01788     if (args.size() > 1) {
01789       singleShot = (id == Window::SetTimeout);
01790       i = args[1].toInt32(exec);
01791     } else {
01792       // second parameter is missing. Emulate Mozilla behavior.
01793       singleShot = true;
01794       i = 4;
01795     }
01796     if (v.isA(StringType)) {
01797       int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot );
01798       return Number(r);
01799     }
01800     else if (v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
01801       Object func = Object::dynamicCast(v);
01802       List funcArgs;
01803       ListIterator it = args.begin();
01804       int argno = 0;
01805       while (it != args.end()) {
01806     Value arg = it++;
01807     if (argno++ >= 2)
01808         funcArgs.append(arg);
01809       }
01810       if (args.size() < 2)
01811     funcArgs.append(Number(i));
01812       int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot );
01813       return Number(r);
01814     }
01815     else
01816       return Undefined();
01817   }
01818   case Window::ClearTimeout:
01819   case Window::ClearInterval:
01820     (const_cast<Window*>(window))->winq->clearTimeout(v.toInt32(exec));
01821     return Undefined();
01822   case Window::Print:
01823     if ( widget ) {
01824       // ### TODO emit onbeforeprint event
01825       widget->print();
01826       // ### TODO emit onafterprint event
01827     }
01828   case Window::CaptureEvents:
01829   case Window::ReleaseEvents:
01830     // Do nothing for now. These are NS-specific legacy calls.
01831     break;
01832   case Window::AddEventListener: {
01833         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01834         if (listener) {
01835         DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
01836             docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
01837         }
01838         return Undefined();
01839     }
01840   case Window::RemoveEventListener: {
01841         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01842         if (listener) {
01843         DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
01844             docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
01845         }
01846         return Undefined();
01847     }
01848 
01849   }
01850   return Undefined();
01851 }
01852 
01854 
01855 // KDE 4: Make those parameters const ... &
01856 ScheduledAction::ScheduledAction(Object _func, List _args, QTime _nextTime, int _interval, bool _singleShot,
01857                   int _timerId)
01858 {
01859   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
01860   func = static_cast<ObjectImp*>(_func.imp());
01861   args = _args;
01862   isFunction = true;
01863   singleShot = _singleShot;
01864   nextTime = _nextTime;
01865   interval = _interval;
01866   executing = false;
01867   timerId = _timerId;
01868 }
01869 
01870 // KDE 4: Make it const QString &
01871 ScheduledAction::ScheduledAction(QString _code, QTime _nextTime, int _interval, bool _singleShot, int _timerId)
01872 {
01873   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
01874   //func = 0;
01875   //args = 0;
01876   func = 0;
01877   code = _code;
01878   isFunction = false;
01879   singleShot = _singleShot;
01880   nextTime = _nextTime;
01881   interval = _interval;
01882   executing = false;
01883   timerId = _timerId;
01884 }
01885 
01886 bool ScheduledAction::execute(Window *window)
01887 {
01888   KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
01889   if (!part || !part->jScriptEnabled())
01890     return false;
01891   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter());
01892 
01893   interpreter->setProcessingTimerCallback(true);
01894 
01895   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
01896   if (isFunction) {
01897     if (func->implementsCall()) {
01898       // #### check this
01899       Q_ASSERT( part );
01900       if ( part )
01901       {
01902         KJS::Interpreter *interpreter = part->jScript()->interpreter();
01903         ExecState *exec = interpreter->globalExec();
01904         Q_ASSERT( window == interpreter->globalObject().imp() );
01905         Object obj( window );
01906         func->call(exec,obj,args); // note that call() creates its own execution state for the func call
01907         if (exec->hadException())
01908           exec->clearException();
01909 
01910         // Update our document's rendering following the execution of the timeout callback.
01911         part->document().updateRendering();
01912       }
01913     }
01914   }
01915   else {
01916     part->executeScript(DOM::Node(), code);
01917   }
01918 
01919   interpreter->setProcessingTimerCallback(false);
01920   return true;
01921 }
01922 
01923 void ScheduledAction::mark()
01924 {
01925   if (func && !func->marked())
01926     func->mark();
01927   args.mark();
01928 }
01929 
01930 ScheduledAction::~ScheduledAction()
01931 {
01932   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
01933 }
01934 
01936 
01937 WindowQObject::WindowQObject(Window *w)
01938   : parent(w)
01939 {
01940   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
01941   if ( !parent->m_frame )
01942       kdDebug(6070) << "WARNING: null part in " << k_funcinfo << endl;
01943   else
01944       connect( parent->m_frame, SIGNAL( destroyed() ),
01945                this, SLOT( parentDestroyed() ) );
01946   pausedTime = 0;
01947   lastTimerId = 0;
01948   currentlyDispatching = false;
01949 }
01950 
01951 WindowQObject::~WindowQObject()
01952 {
01953   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
01954   parentDestroyed(); // reuse same code
01955 }
01956 
01957 void WindowQObject::parentDestroyed()
01958 {
01959   killTimers();
01960 
01961   QPtrListIterator<ScheduledAction> it(scheduledActions);
01962   for (; it.current(); ++it)
01963     delete it.current();
01964   scheduledActions.clear();
01965 }
01966 
01967 int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot)
01968 {
01969   int id = ++lastTimerId;
01970   if (t < 10) t = 10;
01971   QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t);
01972   ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id);
01973   scheduledActions.append(action);
01974   setNextTimer();
01975   return id;
01976 }
01977 
01978 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
01979 {
01980   Object objFunc = Object::dynamicCast( func );
01981   if (!objFunc.isValid())
01982     return 0;
01983   int id = ++lastTimerId;
01984   if (t < 10) t = 10;
01985   QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t);
01986   ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id);
01987   scheduledActions.append(action);
01988   setNextTimer();
01989   return id;
01990 }
01991 
01992 void WindowQObject::clearTimeout(int timerId)
01993 {
01994   QPtrListIterator<ScheduledAction> it(scheduledActions);
01995   for (; it.current(); ++it) {
01996     ScheduledAction *action = it.current();
01997     if (action->timerId == timerId) {
01998       scheduledActions.removeRef(action);
01999       if (!action->executing)
02000     delete action;
02001       return;
02002     }
02003   }
02004 }
02005 
02006 bool WindowQObject::hasTimers() const
02007 {
02008   return scheduledActions.count();
02009 }
02010 
02011 void WindowQObject::mark()
02012 {
02013   QPtrListIterator<ScheduledAction> it(scheduledActions);
02014   for (; it.current(); ++it)
02015     it.current()->mark();
02016 }
02017 
02018 void WindowQObject::timerEvent(QTimerEvent *)
02019 {
02020   killTimers();
02021 
02022   if (scheduledActions.isEmpty())
02023     return;
02024 
02025   currentlyDispatching = true;
02026 
02027   QTime currentActual = QTime::currentTime();
02028   QTime currentAdjusted = currentActual.addMSecs(-pausedTime);
02029 
02030   // Work out which actions are to be executed. We take a separate copy of
02031   // this list since the main one may be modified during action execution
02032   QPtrList<ScheduledAction> toExecute;
02033   QPtrListIterator<ScheduledAction> it(scheduledActions);
02034   for (; it.current(); ++it)
02035     if (currentAdjusted >= it.current()->nextTime)
02036       toExecute.append(it.current());
02037 
02038   // ### verify that the window can't be closed (and action deleted) during execution
02039   it = QPtrListIterator<ScheduledAction>(toExecute);
02040   for (; it.current(); ++it) {
02041     ScheduledAction *action = it.current();
02042     if (!scheduledActions.containsRef(action)) // removed by clearTimeout()
02043       continue;
02044 
02045     action->executing = true; // prevent deletion in clearTimeout()
02046 
02047     if (parent->part()) {
02048       bool ok = action->execute(parent);
02049       if ( !ok ) // e.g. JS disabled
02050         scheduledActions.removeRef( action );
02051     }
02052 
02053     if (action->singleShot) {
02054       scheduledActions.removeRef(action);
02055     }
02056 
02057     action->executing = false;
02058 
02059     if (!scheduledActions.containsRef(action))
02060       delete action;
02061     else
02062       action->nextTime = action->nextTime.addMSecs(action->interval);
02063   }
02064 
02065   pausedTime += currentActual.msecsTo(QTime::currentTime());
02066 
02067   currentlyDispatching = false;
02068 
02069   // Work out when next event is to occur
02070   setNextTimer();
02071 }
02072 
02073 void WindowQObject::setNextTimer()
02074 {
02075   if (currentlyDispatching)
02076     return; // Will schedule at the end 
02077 
02078   if (scheduledActions.isEmpty())
02079     return;
02080 
02081   QPtrListIterator<ScheduledAction> it(scheduledActions);
02082   QTime nextTime = it.current()->nextTime;
02083   for (++it; it.current(); ++it)
02084     if (nextTime > it.current()->nextTime)
02085       nextTime = it.current()->nextTime;
02086 
02087   QTime nextTimeActual = nextTime.addMSecs(pausedTime);
02088   int nextInterval = QTime::currentTime().msecsTo(nextTimeActual);
02089   if (nextInterval < 0)
02090     nextInterval = 0;
02091   startTimer(nextInterval);
02092 }
02093 
02094 void WindowQObject::timeoutClose()
02095 {
02096   parent->closeNow();
02097 }
02098 
02099 Value FrameArray::get(ExecState *exec, const Identifier &p) const
02100 {
02101 #ifdef KJS_VERBOSE
02102   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
02103 #endif
02104   if (part.isNull())
02105     return Undefined();
02106 
02107   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
02108   unsigned int len = frames.count();
02109   if (p == lengthPropertyName)
02110     return Number(len);
02111   else if (p== "location") // non-standard property, but works in NS and IE
02112   {
02113     Object obj = Object::dynamicCast( Window::retrieve( part ) );
02114     if ( obj.isValid() )
02115       return obj.get( exec, "location" );
02116     return Undefined();
02117   }
02118 
02119   // check for the name or number
02120   KParts::ReadOnlyPart *frame = part->findFramePart(p.qstring());
02121   if (!frame) {
02122     bool ok;
02123     unsigned int i = p.toArrayIndex(&ok);
02124     if (ok && i < len)
02125       frame = frames.at(i);
02126   }
02127 
02128   // we are potentially fetching a reference to a another Window object here.
02129   // i.e. we may be accessing objects from another interpreter instance.
02130   // Therefore we have to be a bit careful with memory management.
02131   if (frame) {
02132     return Window::retrieve(frame);
02133   }
02134 
02135   return ObjectImp::get(exec, p);
02136 }
02137 
02139 
02140 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
02141 /*
02142 @begin LocationTable 11
02143   hash      Location::Hash      DontDelete
02144   host      Location::Host      DontDelete
02145   hostname  Location::Hostname  DontDelete
02146   href      Location::Href      DontDelete
02147   pathname  Location::Pathname  DontDelete
02148   port      Location::Port      DontDelete
02149   protocol  Location::Protocol  DontDelete
02150   search    Location::Search    DontDelete
02151   [[==]]    Location::EqualEqual    DontDelete|ReadOnly
02152   assign    Location::Assign    DontDelete|Function 1
02153   toString  Location::ToString  DontDelete|Function 0
02154   replace   Location::Replace   DontDelete|Function 1
02155   reload    Location::Reload    DontDelete|Function 0
02156 @end
02157 */
02158 IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
02159 Location::Location(khtml::ChildFrame *f) : m_frame(f)
02160 {
02161   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
02162 }
02163 
02164 Location::~Location()
02165 {
02166   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
02167 }
02168 
02169 KParts::ReadOnlyPart *Location::part() const {
02170   return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : 0L;
02171 }
02172 
02173 Value Location::get(ExecState *exec, const Identifier &p) const
02174 {
02175 #ifdef KJS_VERBOSE
02176   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
02177 #endif
02178 
02179   if (m_frame.isNull() || m_frame->m_part.isNull())
02180     return Undefined();
02181 
02182   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
02183 
02184   // properties that work on all Location objects
02185   if ( entry && entry->value == Replace )
02186       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02187 
02188   // XSS check
02189   const Window* window = Window::retrieveWindow( m_frame->m_part );
02190   if ( !window || !window->isSafeScript(exec) )
02191     return Undefined();
02192 
02193   KURL url = m_frame->m_part->url();
02194   if (entry)
02195     switch (entry->value) {
02196     case Hash:
02197       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
02198     case Host: {
02199       UString str = url.host();
02200       if (url.port())
02201         str += ":" + QString::number((int)url.port());
02202       return String(str);
02203       // Note: this is the IE spec. The NS spec swaps the two, it says
02204       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
02205       // Bleh.
02206     }
02207     case Hostname:
02208       return String( url.host() );
02209     case Href:
02210       if (!url.hasPath())
02211         return String( url.prettyURL()+"/" );
02212       else
02213         return String( url.prettyURL() );
02214     case Pathname:
02215       return String( url.path().isEmpty() ? QString("/") : url.path() );
02216     case Port:
02217       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
02218     case Protocol:
02219       return String( url.protocol()+":" );
02220     case Search:
02221       return String( url.query() );
02222     case EqualEqual: // [[==]]
02223       return String(toString(exec));
02224     case ToString:
02225       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02226     }
02227   // Look for overrides
02228   ValueImp * val = ObjectImp::getDirect(p);
02229   if (val)
02230     return Value(val);
02231   if (entry && (entry->attr & Function))
02232     return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02233 
02234   return Undefined();
02235 }
02236 
02237 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
02238 {
02239 #ifdef KJS_VERBOSE
02240   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
02241 #endif
02242   if (m_frame.isNull() || m_frame->m_part.isNull())
02243     return;
02244 
02245   const Window* window = Window::retrieveWindow( m_frame->m_part );
02246   if ( !window )
02247     return;
02248 
02249   KURL url = m_frame->m_part->url();
02250 
02251   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
02252 
02253   if (entry) {
02254 
02255     // XSS check. Only new hrefs can be set from other sites
02256     if (entry->value != Href && !window->isSafeScript(exec))
02257       return;
02258 
02259     QString str = v.toString(exec).qstring();
02260     switch (entry->value) {
02261     case Href: {
02262       KHTMLPart* p =::qt_cast<KHTMLPart*>(Window::retrieveActive(exec)->part());
02263       if ( p )
02264         url = p->htmlDocument().completeURL( str ).string();
02265       else
02266         url = str;
02267       break;
02268     }
02269     case Hash:
02270       // when the hash is already the same ignore it
02271       if (str == url.ref()) return;
02272       url.setRef(str);
02273       break;
02274     case Host: {
02275       QString host = str.left(str.find(":"));
02276       QString port = str.mid(str.find(":")+1);
02277       url.setHost(host);
02278       url.setPort(port.toUInt());
02279       break;
02280     }
02281     case Hostname:
02282       url.setHost(str);
02283       break;
02284     case Pathname:
02285       url.setPath(str);
02286       break;
02287     case Port:
02288       url.setPort(str.toUInt());
02289       break;
02290     case Protocol:
02291       url.setProtocol(str);
02292       break;
02293     case Search:
02294       url.setQuery(str);
02295       break;
02296     }
02297   } else {
02298     ObjectImp::put(exec, p, v, attr);
02299     return;
02300   }
02301 
02302   Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
02303 }
02304 
02305 Value Location::toPrimitive(ExecState *exec, Type) const
02306 {
02307   if (m_frame) {
02308     Window* window = Window::retrieveWindow( m_frame->m_part );
02309     if ( window && window->isSafeScript(exec) )
02310       return String(toString(exec));
02311   }
02312   return Undefined();
02313 }
02314 
02315 UString Location::toString(ExecState *exec) const
02316 {
02317   if (m_frame) {
02318     Window* window = Window::retrieveWindow( m_frame->m_part );
02319     if ( window && window->isSafeScript(exec) )
02320     {
02321       if (!m_frame->m_part->url().hasPath())
02322         return m_frame->m_part->url().prettyURL()+"/";
02323       else
02324         return m_frame->m_part->url().prettyURL();
02325     }
02326   }
02327   return "";
02328 }
02329 
02330 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02331 {
02332   KJS_CHECK_THIS( Location, thisObj );
02333   Location *location = static_cast<Location *>(thisObj.imp());
02334   KParts::ReadOnlyPart *part = location->part();
02335 
02336   if (!part) return Undefined();
02337 
02338   Window* window = Window::retrieveWindow(part);
02339 
02340   if ( !window->isSafeScript(exec) && id != Location::Replace)
02341       return Undefined();
02342 
02343   switch (id) {
02344   case Location::Assign:
02345   case Location::Replace:
02346     Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(),
02347             id == Location::Replace);
02348     break;
02349   case Location::Reload: {
02350     KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart *>(part);
02351     if (part)
02352       khtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
02353     break;
02354   }
02355   case Location::ToString:
02356     return String(location->toString(exec));
02357   }
02358   return Undefined();
02359 }
02360 
02362 
02363 const ClassInfo External::info = { "External", 0, 0, 0 };
02364 /*
02365 @begin ExternalTable 4
02366   addFavorite   External::AddFavorite   DontDelete|Function 1
02367 @end
02368 */
02369 IMPLEMENT_PROTOFUNC_DOM(ExternalFunc)
02370 
02371 Value External::get(ExecState *exec, const Identifier &p) const
02372 {
02373   return lookupGetFunction<ExternalFunc,ObjectImp>(exec,p,&ExternalTable,this);
02374 }
02375 
02376 Value ExternalFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02377 {
02378   KJS_CHECK_THIS( External, thisObj );
02379   External *external = static_cast<External *>(thisObj.imp());
02380 
02381   KHTMLPart *part = external->part;
02382   if (!part)
02383     return Undefined();
02384 
02385   KHTMLView *widget = part->view();
02386 
02387   switch (id) {
02388   case External::AddFavorite:
02389   {
02390 #ifndef KONQ_EMBEDDED
02391     if (!widget->dialogsAllowed())
02392       return Undefined();
02393     part->xmlDocImpl()->updateRendering();
02394     if (args.size() != 1 && args.size() != 2)
02395       return Undefined();
02396 
02397     QString url = args[0].toString(exec).qstring();
02398     QString title;
02399     if (args.size() == 2)
02400       title = args[1].toString(exec).qstring();
02401 
02402     // AK - don't do anything yet, for the moment i
02403     // just wanted the base js handling code in cvs
02404     return Undefined();
02405 
02406     QString question;
02407     if ( title.isEmpty() )
02408       question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?")
02409                  .arg(url);
02410     else
02411       question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?")
02412                  .arg(url).arg(title);
02413 
02414     emit part->browserExtension()->requestFocus(part);
02415 
02416     QString caption;
02417     if (!part->url().host().isEmpty())
02418        caption = part->url().host() + " - ";
02419     caption += i18n("JavaScript Attempted Bookmark Insert");
02420 
02421     if (KMessageBox::warningYesNo(
02422           widget, question, caption,
02423           i18n("Insert"), i18n("Disallow")) == KMessageBox::Yes)
02424     {
02425       KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
02426       mgr->addBookmarkDialog(url,title);
02427     }
02428 #else
02429     return Undefined();
02430 #endif
02431     break;
02432   }
02433   default:
02434     return Undefined();
02435   }
02436 
02437   return Undefined();
02438 }
02439 
02441 
02442 const ClassInfo History::info = { "History", 0, 0, 0 };
02443 /*
02444 @begin HistoryTable 4
02445   length    History::Length     DontDelete|ReadOnly
02446   back      History::Back       DontDelete|Function 0
02447   forward   History::Forward    DontDelete|Function 0
02448   go        History::Go     DontDelete|Function 1
02449 @end
02450 */
02451 IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
02452 
02453 Value History::get(ExecState *exec, const Identifier &p) const
02454 {
02455   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
02456 }
02457 
02458 Value History::getValueProperty(ExecState *, int token) const
02459 {
02460   // if previous or next is implemented, make sure its not a major
02461   // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/)
02462   switch (token) {
02463   case Length:
02464   {
02465     if ( !part )
02466       return Number( 0 );
02467 
02468     KParts::BrowserExtension *ext = part->browserExtension();
02469     if ( !ext )
02470       return Number( 0 );
02471 
02472     KParts::BrowserInterface *iface = ext->browserInterface();
02473     if ( !iface )
02474       return Number( 0 );
02475 
02476     QVariant length = iface->property( "historyLength" );
02477 
02478     if ( length.type() != QVariant::UInt )
02479       return Number( 0 );
02480 
02481     return Number( length.toUInt() );
02482   }
02483   default:
02484     kdDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token << endl;
02485     return Undefined();
02486   }
02487 }
02488 
02489 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02490 {
02491   KJS_CHECK_THIS( History, thisObj );
02492   History *history = static_cast<History *>(thisObj.imp());
02493 
02494   Value v = args[0];
02495   Number n;
02496   if(v.isValid())
02497     n = v.toInteger(exec);
02498 
02499   int steps;
02500   switch (id) {
02501   case History::Back:
02502     steps = -1;
02503     break;
02504   case History::Forward:
02505     steps = 1;
02506     break;
02507   case History::Go:
02508     steps = n.intValue();
02509     break;
02510   default:
02511     return Undefined();
02512   }
02513 
02514   // Special case for go(0) from a frame -> reload only the frame
02515   // go(i!=0) from a frame navigates into the history of the frame only,
02516   // in both IE and NS (but not in Mozilla).... we can't easily do that
02517   // in Konqueror...
02518   if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
02519   {
02520     history->part->openURL( history->part->url() ); 
02521   } else
02522   {
02523     // Delay it.
02524     // Testcase: history.back(); alert("hello");
02525     Window* window = Window::retrieveWindow( history->part );
02526     window->delayedGoHistory( steps );
02527   }
02528   return Undefined();
02529 }
02530 
02532 
02533 #ifdef Q_WS_QWS
02534 
02535 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
02536 
02537 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
02538 {
02539   if ( p.qstring().startsWith( "goHistory" ) ) return false;
02540 
02541   return true;
02542 }
02543 
02544 Value Konqueror::get(ExecState *exec, const Identifier &p) const
02545 {
02546   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
02547     return Undefined();
02548 
02549   KParts::BrowserExtension *ext = part->browserExtension();
02550   if ( ext ) {
02551     KParts::BrowserInterface *iface = ext->browserInterface();
02552     if ( iface ) {
02553       QVariant prop = iface->property( p.qstring().latin1() );
02554 
02555       if ( prop.isValid() ) {
02556         switch( prop.type() ) {
02557         case QVariant::Int:
02558           return Number( prop.toInt() );
02559         case QVariant::String:
02560           return String( prop.toString() );
02561         default:
02562           break;
02563         }
02564       }
02565     }
02566   }
02567 
02568   return Value( new KonquerorFunc(exec, this, p.qstring().latin1() ) );
02569 }
02570 
02571 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
02572 {
02573   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
02574 
02575   if (!ext)
02576     return Undefined();
02577 
02578   KParts::BrowserInterface *iface = ext->browserInterface();
02579 
02580   if ( !iface )
02581     return Undefined();
02582 
02583   QCString n = m_name.data();
02584   n += "()";
02585   iface->callMethod( n.data(), QVariant() );
02586 
02587   return Undefined();
02588 }
02589 
02590 UString Konqueror::toString(ExecState *) const
02591 {
02592   return UString("[object Konqueror]");
02593 }
02594 
02595 #endif
02596 
02597 
02598 #include "kjs_window.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys