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( 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   KHTMLPart *part = ::qt_cast<KHTMLPart *>( m_frame->m_part );
01524   KJS::Interpreter *interpreter = part->jScript()->interpreter();
01525   ExecState *exec = interpreter->globalExec();
01526 
01527   QValueList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo;
01528   m_suppressedWindowInfo.clear();
01529   QValueList<SuppressedWindowInfo>::Iterator it = suppressedWindowInfo.begin();
01530   for ( ; it != suppressedWindowInfo.end() ; ++it ) {
01531     executeOpenWindow(exec, (*it).url, (*it).frameName, (*it).features);
01532   }
01533 }
01534 
01535 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01536 {
01537   KJS_CHECK_THIS( Window, thisObj );
01538   Window *window = static_cast<Window *>(thisObj.imp());
01539   QString str, str2;
01540 
01541   KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
01542   if (!part)
01543     return Undefined();
01544 
01545   KHTMLView *widget = part->view();
01546   Value v = args[0];
01547   UString s = v.toString(exec);
01548   str = s.qstring();
01549 
01550   QString caption;
01551   if (part && !part->url().host().isEmpty())
01552     caption = part->url().host() + " - ";
01553   caption += "JavaScript"; // TODO: i18n
01554   // functions that work everywhere
01555   switch(id) {
01556   case Window::Alert:
01557     if (!widget->dialogsAllowed())
01558       return Undefined();
01559     if ( part && part->xmlDocImpl() )
01560       part->xmlDocImpl()->updateRendering();
01561     if ( part )
01562       emit part->browserExtension()->requestFocus(part);
01563     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), caption);
01564     return Undefined();
01565   case Window::Confirm:
01566     if (!widget->dialogsAllowed())
01567       return Undefined();
01568     if ( part && part->xmlDocImpl() )
01569       part->xmlDocImpl()->updateRendering();
01570     if ( part )
01571       emit part->browserExtension()->requestFocus(part);
01572     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), caption,
01573                                                 KStdGuiItem::ok(), KStdGuiItem::cancel()) == KMessageBox::Yes));
01574   case Window::Prompt:
01575 #ifndef KONQ_EMBEDDED
01576     if (!widget->dialogsAllowed())
01577       return Undefined();
01578     if ( part && part->xmlDocImpl() )
01579       part->xmlDocImpl()->updateRendering();
01580     if ( part )
01581       emit part->browserExtension()->requestFocus(part);
01582     bool ok;
01583     if (args.size() >= 2)
01584       str2 = KInputDialog::getText(caption,
01585                                    QStyleSheet::convertFromPlainText(str),
01586                                    args[1].toString(exec).qstring(), &ok, widget);
01587     else
01588       str2 = KInputDialog::getText(caption,
01589                                    QStyleSheet::convertFromPlainText(str),
01590                                    QString::null, &ok, widget);
01591     if ( ok )
01592         return String(str2);
01593     else
01594         return Null();
01595 #else
01596     return Undefined();
01597 #endif
01598   case Window::GetComputedStyle:  {
01599        if ( !part || !part->xmlDocImpl() )
01600          return Undefined();
01601         DOM::Node arg0 = toNode(args[0]);
01602         if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
01603           return Undefined(); // throw exception?
01604         else
01605           return getDOMCSSStyleDeclaration(exec, part->document().defaultView().getComputedStyle(static_cast<DOM::Element>(arg0),
01606                                                                               args[1].toString(exec).string()));
01607       }
01608   case Window::Open:
01609     return window->openWindow(exec, args);
01610   case Window::Close: {
01611     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
01612        The close method closes only windows opened by JavaScript using the open method.
01613        If you attempt to close any other window, a confirm is generated, which
01614        lets the user choose whether the window closes.
01615        This is a security feature to prevent "mail bombs" containing self.close().
01616        However, if the window has only one document (the current one) in its
01617        session history, the close is allowed without any confirm. This is a
01618        special case for one-off windows that need to open other windows and
01619        then dispose of themselves.
01620     */
01621     bool doClose = false;
01622     if (!part->openedByJS())
01623     {
01624       // To conform to the SPEC, we only ask if the window
01625       // has more than one entry in the history (NS does that too).
01626       History history(exec,part);
01627 
01628       if ( history.get( exec, "length" ).toInt32(exec) <= 1 )
01629       {
01630         doClose = true;
01631       }
01632       else
01633       {
01634         // Can we get this dialog with tabs??? Does it close the window or the tab in that case?
01635         emit part->browserExtension()->requestFocus(part);
01636         if ( KMessageBox::questionYesNo( window->part()->widget(),
01637                                          i18n("Close window?"), i18n("Confirmation Required"),
01638                                          KStdGuiItem::close(), KStdGuiItem::cancel() )
01639              == KMessageBox::Yes )
01640           doClose = true;
01641       }
01642     }
01643     else
01644       doClose = true;
01645 
01646     if (doClose)
01647     {
01648       // If this is the current window (the one the interpreter runs in),
01649       // then schedule a delayed close (so that the script terminates first).
01650       // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
01651       if ( Window::retrieveActive(exec) == window ) {
01652         if (widget) {
01653           // quit all dialogs of this view
01654           // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
01655           widget->closeChildDialogs();
01656         }
01657         //kdDebug() << "scheduling delayed close"  << endl;
01658         // We'll close the window at the end of the script execution
01659         Window* w = const_cast<Window*>(window);
01660         w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
01661       } else {
01662         //kdDebug() << "closing NOW"  << endl;
01663         (const_cast<Window*>(window))->closeNow();
01664       }
01665     }
01666     return Undefined();
01667   }
01668   case Window::Navigate:
01669     window->goURL(exec, args[0].toString(exec).qstring(), false /*don't lock history*/);
01670     return Undefined();
01671   case Window::Focus: {
01672     KHTMLSettings::KJSWindowFocusPolicy policy =
01673         part->settings()->windowFocusPolicy(part->url().host());
01674     if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) {
01675       widget->topLevelWidget()->raise();
01676       KWin::deIconifyWindow( widget->topLevelWidget()->winId() );
01677       widget->setActiveWindow();
01678       emit part->browserExtension()->requestFocus(part);
01679     }
01680     return Undefined();
01681   }
01682   case Window::Blur:
01683     // TODO
01684     return Undefined();
01685   case Window::BToA:
01686   case Window::AToB: {
01687       if (!s.is8Bit())
01688           return Undefined();
01689        QByteArray  in, out;
01690        char *binData = s.ascii();
01691        in.setRawData( binData, s.size() );
01692        if (id == Window::AToB)
01693            KCodecs::base64Decode( in, out );
01694        else
01695            KCodecs::base64Encode( in, out );
01696        in.resetRawData( binData, s.size() );
01697        UChar *d = new UChar[out.size()];
01698        for (uint i = 0; i < out.size(); i++)
01699            d[i].uc = (uchar) out[i];
01700        UString ret(d, out.size(), false /*no copy*/);
01701        return String(ret);
01702   }
01703 
01704   };
01705 
01706 
01707   // now unsafe functions..
01708   if (!window->isSafeScript(exec))
01709     return Undefined();
01710 
01711   switch (id) {
01712   case Window::ScrollBy:
01713     if(args.size() == 2 && widget)
01714       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
01715     return Undefined();
01716   case Window::Scroll:
01717   case Window::ScrollTo:
01718     if(args.size() == 2 && widget)
01719       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
01720     return Undefined();
01721   case Window::MoveBy: {
01722     KHTMLSettings::KJSWindowMovePolicy policy =
01723         part->settings()->windowMovePolicy(part->url().host());
01724     if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
01725     {
01726       KParts::BrowserExtension *ext = part->browserExtension();
01727       if (ext) {
01728         QWidget * tl = widget->topLevelWidget();
01729         QRect sg = KGlobalSettings::desktopGeometry(tl);
01730 
01731         QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
01732         // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01733         if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
01734              dest.x()+tl->width() <= sg.width()+sg.x() &&
01735              dest.y()+tl->height() <= sg.height()+sg.y() )
01736           emit ext->moveTopLevelWidget( dest.x(), dest.y() );
01737       }
01738     }
01739     return Undefined();
01740   }
01741   case Window::MoveTo: {
01742     KHTMLSettings::KJSWindowMovePolicy policy =
01743         part->settings()->windowMovePolicy(part->url().host());
01744     if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
01745     {
01746       KParts::BrowserExtension *ext = part->browserExtension();
01747       if (ext) {
01748         QWidget * tl = widget->topLevelWidget();
01749         QRect sg = KGlobalSettings::desktopGeometry(tl);
01750 
01751         QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
01752         // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01753         if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
01754              dest.x()+tl->width() <= sg.width()+sg.x() &&
01755              dest.y()+tl->height() <= sg.height()+sg.y() )
01756         emit ext->moveTopLevelWidget( dest.x(), dest.y() );
01757       }
01758     }
01759     return Undefined();
01760   }
01761   case Window::ResizeBy: {
01762     KHTMLSettings::KJSWindowResizePolicy policy =
01763         part->settings()->windowResizePolicy(part->url().host());
01764     if(policy == KHTMLSettings::KJSWindowResizeAllow
01765             && args.size() == 2 && widget)
01766     {
01767       QWidget * tl = widget->topLevelWidget();
01768       QRect geom = tl->frameGeometry();
01769       window->resizeTo( tl,
01770                         geom.width() + args[0].toInt32(exec),
01771                         geom.height() + args[1].toInt32(exec) );
01772     }
01773     return Undefined();
01774   }
01775   case Window::ResizeTo: {
01776     KHTMLSettings::KJSWindowResizePolicy policy =
01777                part->settings()->windowResizePolicy(part->url().host());
01778     if(policy == KHTMLSettings::KJSWindowResizeAllow
01779                && args.size() == 2 && widget)
01780     {
01781       QWidget * tl = widget->topLevelWidget();
01782       window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
01783     }
01784     return Undefined();
01785   }
01786   case Window::SetTimeout:
01787   case Window::SetInterval: {
01788     bool singleShot;
01789     int i; // timeout interval
01790     if (args.size() == 0)
01791       return Undefined();
01792     if (args.size() > 1) {
01793       singleShot = (id == Window::SetTimeout);
01794       i = args[1].toInt32(exec);
01795     } else {
01796       // second parameter is missing. Emulate Mozilla behavior.
01797       singleShot = true;
01798       i = 4;
01799     }
01800     if (v.isA(StringType)) {
01801       int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot );
01802       return Number(r);
01803     }
01804     else if (v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
01805       Object func = Object::dynamicCast(v);
01806       List funcArgs;
01807       ListIterator it = args.begin();
01808       int argno = 0;
01809       while (it != args.end()) {
01810     Value arg = it++;
01811     if (argno++ >= 2)
01812         funcArgs.append(arg);
01813       }
01814       if (args.size() < 2)
01815     funcArgs.append(Number(i));
01816       int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot );
01817       return Number(r);
01818     }
01819     else
01820       return Undefined();
01821   }
01822   case Window::ClearTimeout:
01823   case Window::ClearInterval:
01824     (const_cast<Window*>(window))->winq->clearTimeout(v.toInt32(exec));
01825     return Undefined();
01826   case Window::Print:
01827     if ( widget ) {
01828       // ### TODO emit onbeforeprint event
01829       widget->print();
01830       // ### TODO emit onafterprint event
01831     }
01832   case Window::CaptureEvents:
01833   case Window::ReleaseEvents:
01834     // Do nothing for now. These are NS-specific legacy calls.
01835     break;
01836   case Window::AddEventListener: {
01837         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01838         if (listener) {
01839         DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
01840             docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
01841         }
01842         return Undefined();
01843     }
01844   case Window::RemoveEventListener: {
01845         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01846         if (listener) {
01847         DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
01848             docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
01849         }
01850         return Undefined();
01851     }
01852 
01853   }
01854   return Undefined();
01855 }
01856 
01858 
01859 // KDE 4: Make those parameters const ... &
01860 ScheduledAction::ScheduledAction(Object _func, List _args, QTime _nextTime, int _interval, bool _singleShot,
01861                   int _timerId)
01862 {
01863   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
01864   func = static_cast<ObjectImp*>(_func.imp());
01865   args = _args;
01866   isFunction = true;
01867   singleShot = _singleShot;
01868   nextTime = _nextTime;
01869   interval = _interval;
01870   executing = false;
01871   timerId = _timerId;
01872 }
01873 
01874 // KDE 4: Make it const QString &
01875 ScheduledAction::ScheduledAction(QString _code, QTime _nextTime, int _interval, bool _singleShot, int _timerId)
01876 {
01877   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
01878   //func = 0;
01879   //args = 0;
01880   func = 0;
01881   code = _code;
01882   isFunction = false;
01883   singleShot = _singleShot;
01884   nextTime = _nextTime;
01885   interval = _interval;
01886   executing = false;
01887   timerId = _timerId;
01888 }
01889 
01890 bool ScheduledAction::execute(Window *window)
01891 {
01892   KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
01893   if (!part || !part->jScriptEnabled())
01894     return false;
01895   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter());
01896 
01897   interpreter->setProcessingTimerCallback(true);
01898 
01899   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
01900   if (isFunction) {
01901     if (func->implementsCall()) {
01902       // #### check this
01903       Q_ASSERT( part );
01904       if ( part )
01905       {
01906         KJS::Interpreter *interpreter = part->jScript()->interpreter();
01907         ExecState *exec = interpreter->globalExec();
01908         Q_ASSERT( window == interpreter->globalObject().imp() );
01909         Object obj( window );
01910         func->call(exec,obj,args); // note that call() creates its own execution state for the func call
01911         if (exec->hadException())
01912           exec->clearException();
01913 
01914         // Update our document's rendering following the execution of the timeout callback.
01915         part->document().updateRendering();
01916       }
01917     }
01918   }
01919   else {
01920     part->executeScript(DOM::Node(), code);
01921   }
01922 
01923   interpreter->setProcessingTimerCallback(false);
01924   return true;
01925 }
01926 
01927 void ScheduledAction::mark()
01928 {
01929   if (func && !func->marked())
01930     func->mark();
01931   args.mark();
01932 }
01933 
01934 ScheduledAction::~ScheduledAction()
01935 {
01936   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
01937 }
01938 
01940 
01941 WindowQObject::WindowQObject(Window *w)
01942   : parent(w)
01943 {
01944   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
01945   if ( !parent->m_frame )
01946       kdDebug(6070) << "WARNING: null part in " << k_funcinfo << endl;
01947   else
01948       connect( parent->m_frame, SIGNAL( destroyed() ),
01949                this, SLOT( parentDestroyed() ) );
01950   pausedTime = 0;
01951   lastTimerId = 0;
01952   currentlyDispatching = false;
01953 }
01954 
01955 WindowQObject::~WindowQObject()
01956 {
01957   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
01958   parentDestroyed(); // reuse same code
01959 }
01960 
01961 void WindowQObject::parentDestroyed()
01962 {
01963   killTimers();
01964 
01965   QPtrListIterator<ScheduledAction> it(scheduledActions);
01966   for (; it.current(); ++it)
01967     delete it.current();
01968   scheduledActions.clear();
01969 }
01970 
01971 int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot)
01972 {
01973   int id = ++lastTimerId;
01974   if (t < 10) t = 10;
01975   QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t);
01976   ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id);
01977   scheduledActions.append(action);
01978   setNextTimer();
01979   return id;
01980 }
01981 
01982 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
01983 {
01984   Object objFunc = Object::dynamicCast( func );
01985   if (!objFunc.isValid())
01986     return 0;
01987   int id = ++lastTimerId;
01988   if (t < 10) t = 10;
01989   QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t);
01990   ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id);
01991   scheduledActions.append(action);
01992   setNextTimer();
01993   return id;
01994 }
01995 
01996 void WindowQObject::clearTimeout(int timerId)
01997 {
01998   QPtrListIterator<ScheduledAction> it(scheduledActions);
01999   for (; it.current(); ++it) {
02000     ScheduledAction *action = it.current();
02001     if (action->timerId == timerId) {
02002       scheduledActions.removeRef(action);
02003       if (!action->executing)
02004     delete action;
02005       return;
02006     }
02007   }
02008 }
02009 
02010 bool WindowQObject::hasTimers() const
02011 {
02012   return scheduledActions.count();
02013 }
02014 
02015 void WindowQObject::mark()
02016 {
02017   QPtrListIterator<ScheduledAction> it(scheduledActions);
02018   for (; it.current(); ++it)
02019     it.current()->mark();
02020 }
02021 
02022 void WindowQObject::timerEvent(QTimerEvent *)
02023 {
02024   killTimers();
02025 
02026   if (scheduledActions.isEmpty())
02027     return;
02028 
02029   currentlyDispatching = true;
02030 
02031   QTime currentActual = QTime::currentTime();
02032   QTime currentAdjusted = currentActual.addMSecs(-pausedTime);
02033 
02034   // Work out which actions are to be executed. We take a separate copy of
02035   // this list since the main one may be modified during action execution
02036   QPtrList<ScheduledAction> toExecute;
02037   QPtrListIterator<ScheduledAction> it(scheduledActions);
02038   for (; it.current(); ++it)
02039     if (currentAdjusted >= it.current()->nextTime)
02040       toExecute.append(it.current());
02041 
02042   // ### verify that the window can't be closed (and action deleted) during execution
02043   it = QPtrListIterator<ScheduledAction>(toExecute);
02044   for (; it.current(); ++it) {
02045     ScheduledAction *action = it.current();
02046     if (!scheduledActions.containsRef(action)) // removed by clearTimeout()
02047       continue;
02048 
02049     action->executing = true; // prevent deletion in clearTimeout()
02050 
02051     if (parent->part()) {
02052       bool ok = action->execute(parent);
02053       if ( !ok ) // e.g. JS disabled
02054         scheduledActions.removeRef( action );
02055     }
02056 
02057     if (action->singleShot) {
02058       scheduledActions.removeRef(action);
02059     }
02060 
02061     action->executing = false;
02062 
02063     if (!scheduledActions.containsRef(action))
02064       delete action;
02065     else
02066       action->nextTime = action->nextTime.addMSecs(action->interval);
02067   }
02068 
02069   pausedTime += currentActual.msecsTo(QTime::currentTime());
02070 
02071   currentlyDispatching = false;
02072 
02073   // Work out when next event is to occur
02074   setNextTimer();
02075 }
02076 
02077 void WindowQObject::setNextTimer()
02078 {
02079   if (currentlyDispatching)
02080     return; // Will schedule at the end 
02081 
02082   if (scheduledActions.isEmpty())
02083     return;
02084 
02085   QPtrListIterator<ScheduledAction> it(scheduledActions);
02086   QTime nextTime = it.current()->nextTime;
02087   for (++it; it.current(); ++it)
02088     if (nextTime > it.current()->nextTime)
02089       nextTime = it.current()->nextTime;
02090 
02091   QTime nextTimeActual = nextTime.addMSecs(pausedTime);
02092   int nextInterval = QTime::currentTime().msecsTo(nextTimeActual);
02093   if (nextInterval < 0)
02094     nextInterval = 0;
02095   startTimer(nextInterval);
02096 }
02097 
02098 void WindowQObject::timeoutClose()
02099 {
02100   parent->closeNow();
02101 }
02102 
02103 Value FrameArray::get(ExecState *exec, const Identifier &p) const
02104 {
02105 #ifdef KJS_VERBOSE
02106   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
02107 #endif
02108   if (part.isNull())
02109     return Undefined();
02110 
02111   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
02112   unsigned int len = frames.count();
02113   if (p == lengthPropertyName)
02114     return Number(len);
02115   else if (p== "location") // non-standard property, but works in NS and IE
02116   {
02117     Object obj = Object::dynamicCast( Window::retrieve( part ) );
02118     if ( obj.isValid() )
02119       return obj.get( exec, "location" );
02120     return Undefined();
02121   }
02122 
02123   // check for the name or number
02124   KParts::ReadOnlyPart *frame = part->findFramePart(p.qstring());
02125   if (!frame) {
02126     bool ok;
02127     unsigned int i = p.toArrayIndex(&ok);
02128     if (ok && i < len)
02129       frame = frames.at(i);
02130   }
02131 
02132   // we are potentially fetching a reference to a another Window object here.
02133   // i.e. we may be accessing objects from another interpreter instance.
02134   // Therefore we have to be a bit careful with memory management.
02135   if (frame) {
02136     return Window::retrieve(frame);
02137   }
02138 
02139   return ObjectImp::get(exec, p);
02140 }
02141 
02143 
02144 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
02145 /*
02146 @begin LocationTable 11
02147   hash      Location::Hash      DontDelete
02148   host      Location::Host      DontDelete
02149   hostname  Location::Hostname  DontDelete
02150   href      Location::Href      DontDelete
02151   pathname  Location::Pathname  DontDelete
02152   port      Location::Port      DontDelete
02153   protocol  Location::Protocol  DontDelete
02154   search    Location::Search    DontDelete
02155   [[==]]    Location::EqualEqual    DontDelete|ReadOnly
02156   assign    Location::Assign    DontDelete|Function 1
02157   toString  Location::ToString  DontDelete|Function 0
02158   replace   Location::Replace   DontDelete|Function 1
02159   reload    Location::Reload    DontDelete|Function 0
02160 @end
02161 */
02162 IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
02163 Location::Location(khtml::ChildFrame *f) : m_frame(f)
02164 {
02165   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
02166 }
02167 
02168 Location::~Location()
02169 {
02170   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
02171 }
02172 
02173 KParts::ReadOnlyPart *Location::part() const {
02174   return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : 0L;
02175 }
02176 
02177 Value Location::get(ExecState *exec, const Identifier &p) const
02178 {
02179 #ifdef KJS_VERBOSE
02180   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
02181 #endif
02182 
02183   if (m_frame.isNull() || m_frame->m_part.isNull())
02184     return Undefined();
02185 
02186   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
02187 
02188   // properties that work on all Location objects
02189   if ( entry && entry->value == Replace )
02190       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02191 
02192   // XSS check
02193   const Window* window = Window::retrieveWindow( m_frame->m_part );
02194   if ( !window || !window->isSafeScript(exec) )
02195     return Undefined();
02196 
02197   KURL url = m_frame->m_part->url();
02198   if (entry)
02199     switch (entry->value) {
02200     case Hash:
02201       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
02202     case Host: {
02203       UString str = url.host();
02204       if (url.port())
02205         str += ":" + QString::number((int)url.port());
02206       return String(str);
02207       // Note: this is the IE spec. The NS spec swaps the two, it says
02208       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
02209       // Bleh.
02210     }
02211     case Hostname:
02212       return String( url.host() );
02213     case Href:
02214       if (!url.hasPath())
02215         return String( url.prettyURL()+"/" );
02216       else
02217         return String( url.prettyURL() );
02218     case Pathname:
02219       return String( url.path().isEmpty() ? QString("/") : url.path() );
02220     case Port:
02221       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
02222     case Protocol:
02223       return String( url.protocol()+":" );
02224     case Search:
02225       return String( url.query() );
02226     case EqualEqual: // [[==]]
02227       return String(toString(exec));
02228     case ToString:
02229       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02230     }
02231   // Look for overrides
02232   ValueImp * val = ObjectImp::getDirect(p);
02233   if (val)
02234     return Value(val);
02235   if (entry && (entry->attr & Function))
02236     return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
02237 
02238   return Undefined();
02239 }
02240 
02241 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
02242 {
02243 #ifdef KJS_VERBOSE
02244   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
02245 #endif
02246   if (m_frame.isNull() || m_frame->m_part.isNull())
02247     return;
02248 
02249   const Window* window = Window::retrieveWindow( m_frame->m_part );
02250   if ( !window )
02251     return;
02252 
02253   KURL url = m_frame->m_part->url();
02254 
02255   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
02256 
02257   if (entry) {
02258 
02259     // XSS check. Only new hrefs can be set from other sites
02260     if (entry->value != Href && !window->isSafeScript(exec))
02261       return;
02262 
02263     QString str = v.toString(exec).qstring();
02264     switch (entry->value) {
02265     case Href: {
02266       KHTMLPart* p =::qt_cast<KHTMLPart*>(Window::retrieveActive(exec)->part());
02267       if ( p )
02268         url = p->htmlDocument().completeURL( str ).string();
02269       else
02270         url = str;
02271       break;
02272     }
02273     case Hash:
02274       // when the hash is already the same ignore it
02275       if (str == url.ref()) return;
02276       url.setRef(str);
02277       break;
02278     case Host: {
02279       QString host = str.left(str.find(":"));
02280       QString port = str.mid(str.find(":")+1);
02281       url.setHost(host);
02282       url.setPort(port.toUInt());
02283       break;
02284     }
02285     case Hostname:
02286       url.setHost(str);
02287       break;
02288     case Pathname:
02289       url.setPath(str);
02290       break;
02291     case Port:
02292       url.setPort(str.toUInt());
02293       break;
02294     case Protocol:
02295       url.setProtocol(str);
02296       break;
02297     case Search:
02298       url.setQuery(str);
02299       break;
02300     }
02301   } else {
02302     ObjectImp::put(exec, p, v, attr);
02303     return;
02304   }
02305 
02306   Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
02307 }
02308 
02309 Value Location::toPrimitive(ExecState *exec, Type) const
02310 {
02311   if (m_frame) {
02312     Window* window = Window::retrieveWindow( m_frame->m_part );
02313     if ( window && window->isSafeScript(exec) )
02314       return String(toString(exec));
02315   }
02316   return Undefined();
02317 }
02318 
02319 UString Location::toString(ExecState *exec) const
02320 {
02321   if (m_frame) {
02322     Window* window = Window::retrieveWindow( m_frame->m_part );
02323     if ( window && window->isSafeScript(exec) )
02324     {
02325       if (!m_frame->m_part->url().hasPath())
02326         return m_frame->m_part->url().prettyURL()+"/";
02327       else
02328         return m_frame->m_part->url().prettyURL();
02329     }
02330   }
02331   return "";
02332 }
02333 
02334 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02335 {
02336   KJS_CHECK_THIS( Location, thisObj );
02337   Location *location = static_cast<Location *>(thisObj.imp());
02338   KParts::ReadOnlyPart *part = location->part();
02339 
02340   if (!part) return Undefined();
02341 
02342   Window* window = Window::retrieveWindow(part);
02343 
02344   if ( !window->isSafeScript(exec) && id != Location::Replace)
02345       return Undefined();
02346 
02347   switch (id) {
02348   case Location::Assign:
02349   case Location::Replace:
02350     Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(),
02351             id == Location::Replace);
02352     break;
02353   case Location::Reload: {
02354     KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart *>(part);
02355     if (part)
02356       khtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
02357     break;
02358   }
02359   case Location::ToString:
02360     return String(location->toString(exec));
02361   }
02362   return Undefined();
02363 }
02364 
02366 
02367 const ClassInfo External::info = { "External", 0, 0, 0 };
02368 /*
02369 @begin ExternalTable 4
02370   addFavorite   External::AddFavorite   DontDelete|Function 1
02371 @end
02372 */
02373 IMPLEMENT_PROTOFUNC_DOM(ExternalFunc)
02374 
02375 Value External::get(ExecState *exec, const Identifier &p) const
02376 {
02377   return lookupGetFunction<ExternalFunc,ObjectImp>(exec,p,&ExternalTable,this);
02378 }
02379 
02380 Value ExternalFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02381 {
02382   KJS_CHECK_THIS( External, thisObj );
02383   External *external = static_cast<External *>(thisObj.imp());
02384 
02385   KHTMLPart *part = external->part;
02386   if (!part)
02387     return Undefined();
02388 
02389   KHTMLView *widget = part->view();
02390 
02391   switch (id) {
02392   case External::AddFavorite:
02393   {
02394 #ifndef KONQ_EMBEDDED
02395     if (!widget->dialogsAllowed())
02396       return Undefined();
02397     part->xmlDocImpl()->updateRendering();
02398     if (args.size() != 1 && args.size() != 2)
02399       return Undefined();
02400 
02401     QString url = args[0].toString(exec).qstring();
02402     QString title;
02403     if (args.size() == 2)
02404       title = args[1].toString(exec).qstring();
02405 
02406     // AK - don't do anything yet, for the moment i
02407     // just wanted the base js handling code in cvs
02408     return Undefined();
02409 
02410     QString question;
02411     if ( title.isEmpty() )
02412       question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?")
02413                  .arg(url);
02414     else
02415       question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?")
02416                  .arg(url).arg(title);
02417 
02418     emit part->browserExtension()->requestFocus(part);
02419 
02420     QString caption;
02421     if (!part->url().host().isEmpty())
02422        caption = part->url().host() + " - ";
02423     caption += i18n("JavaScript Attempted Bookmark Insert");
02424 
02425     if (KMessageBox::warningYesNo(
02426           widget, question, caption,
02427           i18n("Insert"), i18n("Disallow")) == KMessageBox::Yes)
02428     {
02429       KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
02430       mgr->addBookmarkDialog(url,title);
02431     }
02432 #else
02433     return Undefined();
02434 #endif
02435     break;
02436   }
02437   default:
02438     return Undefined();
02439   }
02440 
02441   return Undefined();
02442 }
02443 
02445 
02446 const ClassInfo History::info = { "History", 0, 0, 0 };
02447 /*
02448 @begin HistoryTable 4
02449   length    History::Length     DontDelete|ReadOnly
02450   back      History::Back       DontDelete|Function 0
02451   forward   History::Forward    DontDelete|Function 0
02452   go        History::Go     DontDelete|Function 1
02453 @end
02454 */
02455 IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
02456 
02457 Value History::get(ExecState *exec, const Identifier &p) const
02458 {
02459   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
02460 }
02461 
02462 Value History::getValueProperty(ExecState *, int token) const
02463 {
02464   // if previous or next is implemented, make sure its not a major
02465   // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/)
02466   switch (token) {
02467   case Length:
02468   {
02469     if ( !part )
02470       return Number( 0 );
02471 
02472     KParts::BrowserExtension *ext = part->browserExtension();
02473     if ( !ext )
02474       return Number( 0 );
02475 
02476     KParts::BrowserInterface *iface = ext->browserInterface();
02477     if ( !iface )
02478       return Number( 0 );
02479 
02480     QVariant length = iface->property( "historyLength" );
02481 
02482     if ( length.type() != QVariant::UInt )
02483       return Number( 0 );
02484 
02485     return Number( length.toUInt() );
02486   }
02487   default:
02488     kdDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token << endl;
02489     return Undefined();
02490   }
02491 }
02492 
02493 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
02494 {
02495   KJS_CHECK_THIS( History, thisObj );
02496   History *history = static_cast<History *>(thisObj.imp());
02497 
02498   Value v = args[0];
02499   Number n;
02500   if(v.isValid())
02501     n = v.toInteger(exec);
02502 
02503   int steps;
02504   switch (id) {
02505   case History::Back:
02506     steps = -1;
02507     break;
02508   case History::Forward:
02509     steps = 1;
02510     break;
02511   case History::Go:
02512     steps = n.intValue();
02513     break;
02514   default:
02515     return Undefined();
02516   }
02517 
02518   // Special case for go(0) from a frame -> reload only the frame
02519   // go(i!=0) from a frame navigates into the history of the frame only,
02520   // in both IE and NS (but not in Mozilla).... we can't easily do that
02521   // in Konqueror...
02522   if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
02523   {
02524     history->part->openURL( history->part->url() ); 
02525   } else
02526   {
02527     // Delay it.
02528     // Testcase: history.back(); alert("hello");
02529     Window* window = Window::retrieveWindow( history->part );
02530     window->delayedGoHistory( steps );
02531   }
02532   return Undefined();
02533 }
02534 
02536 
02537 #ifdef Q_WS_QWS
02538 
02539 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
02540 
02541 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
02542 {
02543   if ( p.qstring().startsWith( "goHistory" ) ) return false;
02544 
02545   return true;
02546 }
02547 
02548 Value Konqueror::get(ExecState *exec, const Identifier &p) const
02549 {
02550   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
02551     return Undefined();
02552 
02553   KParts::BrowserExtension *ext = part->browserExtension();
02554   if ( ext ) {
02555     KParts::BrowserInterface *iface = ext->browserInterface();
02556     if ( iface ) {
02557       QVariant prop = iface->property( p.qstring().latin1() );
02558 
02559       if ( prop.isValid() ) {
02560         switch( prop.type() ) {
02561         case QVariant::Int:
02562           return Number( prop.toInt() );
02563         case QVariant::String:
02564           return String( prop.toString() );
02565         default:
02566           break;
02567         }
02568       }
02569     }
02570   }
02571 
02572   return Value( new KonquerorFunc(exec, this, p.qstring().latin1() ) );
02573 }
02574 
02575 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
02576 {
02577   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
02578 
02579   if (!ext)
02580     return Undefined();
02581 
02582   KParts::BrowserInterface *iface = ext->browserInterface();
02583 
02584   if ( !iface )
02585     return Undefined();
02586 
02587   QCString n = m_name.data();
02588   n += "()";
02589   iface->callMethod( n.data(), QVariant() );
02590 
02591   return Undefined();
02592 }
02593 
02594 UString Konqueror::toString(ExecState *) const
02595 {
02596   return UString("[object Konqueror]");
02597 }
02598 
02599 #endif
02600 
02601 
02602 #include "kjs_window.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys