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