khtml Library API Documentation

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  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public
00018  *  License along with this library; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 #include <qstylesheet.h>
00023 #include <qtimer.h>
00024 #include <qpaintdevicemetrics.h>
00025 #include <qapplication.h>
00026 #include <kdebug.h>
00027 #include <kmessagebox.h>
00028 #include <klineeditdlg.h>
00029 #include <klocale.h>
00030 #include <kparts/browserinterface.h>
00031 #include <kwin.h>
00032 #include <kwinmodule.h>
00033 #include <kconfig.h>
00034 #include <assert.h>
00035 #include <qstyle.h>
00036 #include <qobjectlist.h>
00037 
00038 #include "kjs_proxy.h"
00039 #include "kjs_window.h"
00040 #include "kjs_navigator.h"
00041 #include "kjs_html.h"
00042 #include "kjs_range.h"
00043 #include "kjs_traversal.h"
00044 #include "kjs_css.h"
00045 #include "kjs_events.h"
00046 
00047 #include "khtmlview.h"
00048 #include "khtml_part.h"
00049 #include "khtml_settings.h"
00050 #include "xml/dom2_eventsimpl.h"
00051 #include "xml/dom_docimpl.h"
00052 #include "html/html_documentimpl.h"
00053 
00054 using namespace KJS;
00055 
00056 namespace KJS {
00057 
00059 
00060   class History : public ObjectImp {
00061     friend class HistoryFunc;
00062   public:
00063     History(ExecState *exec, KHTMLPart *p)
00064       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00065     virtual Value get(ExecState *exec, const UString &propertyName) const;
00066     Value getValueProperty(ExecState *exec, int token) const;
00067     virtual const ClassInfo* classInfo() const { return &info; }
00068     static const ClassInfo info;
00069     enum { Back, Forward, Go, Length };
00070   private:
00071     QGuardedPtr<KHTMLPart> part;
00072   };
00073 
00074   class FrameArray : public ObjectImp {
00075   public:
00076     FrameArray(ExecState *exec, KHTMLPart *p)
00077       : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
00078     virtual Value get(ExecState *exec, const UString &propertyName) const;
00079   private:
00080     QGuardedPtr<KHTMLPart> part;
00081   };
00082 
00083 #ifdef Q_WS_QWS
00084   class KonquerorFunc : public DOMFunction {
00085   public:
00086     KonquerorFunc(const Konqueror* k, const char* name)
00087       : DOMFunction(), konqueror(k), m_name(name) { }
00088     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
00089 
00090   private:
00091     const Konqueror* konqueror;
00092     QCString m_name;
00093   };
00094 #endif
00095 } // namespace KJS
00096 
00097 #include "kjs_window.lut.h"
00098 
00100 
00101 // table for screen object
00102 /*
00103 @begin ScreenTable 7
00104   height        Screen::Height          DontEnum|ReadOnly
00105   width         Screen::Width           DontEnum|ReadOnly
00106   colorDepth    Screen::ColorDepth      DontEnum|ReadOnly
00107   pixelDepth    Screen::PixelDepth      DontEnum|ReadOnly
00108   availLeft     Screen::AvailLeft       DontEnum|ReadOnly
00109   availTop      Screen::AvailTop        DontEnum|ReadOnly
00110   availHeight   Screen::AvailHeight     DontEnum|ReadOnly
00111   availWidth    Screen::AvailWidth      DontEnum|ReadOnly
00112 @end
00113 */
00114 
00115 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
00116 
00117 // We set the object prototype so that toString is implemented
00118 Screen::Screen(ExecState *exec)
00119   : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
00120 
00121 Value Screen::get(ExecState *exec, const UString &p) const
00122 {
00123 #ifdef KJS_VERBOSE
00124   kdDebug(6070) << "Screen::get " << p.qstring() << endl;
00125 #endif
00126   return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
00127 }
00128 
00129 Value Screen::getValueProperty(ExecState *exec, int token) const
00130 {
00131   KWinModule info;
00132   QWidget *thisWidget = Window::retrieveActive(exec)->part()->view();
00133   QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(thisWidget));
00134 
00135   switch( token ) {
00136   case Height:
00137     return Number(sg.height());
00138   case Width:
00139     return Number(sg.width());
00140   case ColorDepth:
00141   case PixelDepth: {
00142     QPaintDeviceMetrics m(QApplication::desktop());
00143     return Number(m.depth());
00144   }
00145   case AvailLeft: {
00146     QRect clipped = info.workArea().intersect(sg);
00147     return Number(clipped.x()-sg.x());
00148   }
00149   case AvailTop: {
00150     QRect clipped = info.workArea().intersect(sg);
00151     return Number(clipped.y()-sg.y());
00152   }
00153   case AvailHeight: {
00154     QRect clipped = info.workArea().intersect(sg);
00155     return Number(clipped.height());
00156   }
00157   case AvailWidth: {
00158     QRect clipped = info.workArea().intersect(sg);
00159     return Number(clipped.width());
00160   }
00161   default:
00162     kdWarning(6070) << "Screen::getValueProperty unhandled token " << token << endl;
00163     return Undefined();
00164   }
00165 }
00166 
00168 
00169 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
00170 
00171 /*
00172 @begin WindowTable 86
00173   closed        Window::Closed          DontDelete|ReadOnly
00174   crypto        Window::Crypto          DontDelete|ReadOnly
00175   defaultStatus Window::DefaultStatus   DontDelete
00176   defaultstatus Window::DefaultStatus   DontDelete
00177   status        Window::Status          DontDelete
00178   document      Window::Document        DontDelete|ReadOnly
00179   Node          Window::Node            DontDelete
00180   Event         Window::EventCtor       DontDelete
00181   Range         Window::Range           DontDelete
00182   NodeFilter    Window::NodeFilter      DontDelete
00183   DOMException  Window::DOMException    DontDelete
00184   CSSRule       Window::CSSRule         DontDelete
00185   frames        Window::Frames          DontDelete|ReadOnly
00186   history       Window::_History        DontDelete|ReadOnly
00187   event         Window::Event           DontDelete|ReadOnly
00188   innerHeight   Window::InnerHeight     DontDelete|ReadOnly
00189   innerWidth    Window::InnerWidth      DontDelete|ReadOnly
00190   length        Window::Length          DontDelete|ReadOnly
00191   location      Window::_Location       DontDelete
00192   name          Window::Name            DontDelete
00193   navigator     Window::_Navigator      DontDelete|ReadOnly
00194   clientInformation     Window::ClientInformation       DontDelete|ReadOnly
00195   konqueror     Window::_Konqueror      DontDelete|ReadOnly
00196   offscreenBuffering    Window::OffscreenBuffering      DontDelete|ReadOnly
00197   opener        Window::Opener          DontDelete|ReadOnly
00198   outerHeight   Window::OuterHeight     DontDelete|ReadOnly
00199   outerWidth    Window::OuterWidth      DontDelete|ReadOnly
00200   pageXOffset   Window::PageXOffset     DontDelete|ReadOnly
00201   pageYOffset   Window::PageYOffset     DontDelete|ReadOnly
00202   parent        Window::Parent          DontDelete|ReadOnly
00203   personalbar   Window::Personalbar     DontDelete|ReadOnly
00204   screenX       Window::ScreenX         DontDelete|ReadOnly
00205   screenY       Window::ScreenY         DontDelete|ReadOnly
00206   scrollbars    Window::Scrollbars      DontDelete|ReadOnly
00207   scroll        Window::Scroll          DontDelete|Function 2
00208   scrollBy      Window::ScrollBy        DontDelete|Function 2
00209   scrollTo      Window::ScrollTo        DontDelete|Function 2
00210   moveBy        Window::MoveBy          DontDelete|Function 2
00211   moveTo        Window::MoveTo          DontDelete|Function 2
00212   resizeBy      Window::ResizeBy        DontDelete|Function 2
00213   resizeTo      Window::ResizeTo        DontDelete|Function 2
00214   self          Window::Self            DontDelete|ReadOnly
00215   window        Window::_Window         DontDelete|ReadOnly
00216   top           Window::Top             DontDelete|ReadOnly
00217   screen        Window::_Screen         DontDelete|ReadOnly
00218   Image         Window::Image           DontDelete|ReadOnly
00219   Option        Window::Option          DontDelete|ReadOnly
00220   alert         Window::Alert           DontDelete|Function 1
00221   confirm       Window::Confirm         DontDelete|Function 1
00222   prompt        Window::Prompt          DontDelete|Function 2
00223   open          Window::Open            DontDelete|Function 3
00224   setTimeout    Window::SetTimeout      DontDelete|Function 2
00225   clearTimeout  Window::ClearTimeout    DontDelete|Function 1
00226   focus         Window::Focus           DontDelete|Function 0
00227   blur          Window::Blur            DontDelete|Function 0
00228   close         Window::Close           DontDelete|Function 0
00229   setInterval   Window::SetInterval     DontDelete|Function 2
00230   clearInterval Window::ClearInterval   DontDelete|Function 1
00231   print         Window::Print           DontDelete|Function 0
00232   addEventListener      Window::AddEventListener        DontDelete|Function 3
00233   removeEventListener   Window::RemoveEventListener     DontDelete|Function 3
00234 # Warning, when adding a function to this object you need to add a case in Window::get
00235 # Event handlers
00236 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
00237 # ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll.
00238 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
00239   onabort       Window::Onabort         DontDelete
00240   onblur        Window::Onblur          DontDelete
00241   onchange      Window::Onchange        DontDelete
00242   onclick       Window::Onclick         DontDelete
00243   ondblclick    Window::Ondblclick      DontDelete
00244   ondragdrop    Window::Ondragdrop      DontDelete
00245   onerror       Window::Onerror         DontDelete
00246   onfocus       Window::Onfocus         DontDelete
00247   onkeydown     Window::Onkeydown       DontDelete
00248   onkeypress    Window::Onkeypress      DontDelete
00249   onkeyup       Window::Onkeyup         DontDelete
00250   onload        Window::Onload          DontDelete
00251   onmousedown   Window::Onmousedown     DontDelete
00252   onmousemove   Window::Onmousemove     DontDelete
00253   onmouseout    Window::Onmouseout      DontDelete
00254   onmouseover   Window::Onmouseover     DontDelete
00255   onmouseup     Window::Onmouseup       DontDelete
00256   onmove        Window::Onmove          DontDelete
00257   onreset       Window::Onreset         DontDelete
00258   onresize      Window::Onresize        DontDelete
00259   onselect      Window::Onselect        DontDelete
00260   onsubmit      Window::Onsubmit        DontDelete
00261   onunload      Window::Onunload        DontDelete
00262 @end
00263 */
00264 IMPLEMENT_PROTOFUNC_DOM(WindowFunc)
00265 
00266 Window::Window(KHTMLPart *p)
00267   : ObjectImp(/*no proto*/), m_part(p), screen(0), history(0), m_frames(0), loc(0), m_evt(0)
00268 {
00269   winq = new WindowQObject(this);
00270   //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
00271 }
00272 
00273 Window::~Window()
00274 {
00275   kdDebug(6070) << "Window::~Window this=" << this << " part=" << m_part << endl;
00276   delete winq;
00277 }
00278 
00279 Window *Window::retrieveWindow(KHTMLPart *p)
00280 {
00281   Object obj = Object::dynamicCast( retrieve( p ) );
00282 #ifndef NDEBUG
00283   // obj should never be null, except when javascript has been disabled in that part.
00284   if ( p && p->jScriptEnabled() )
00285   {
00286     assert( !obj.isNull() );
00287 #ifndef QWS
00288     assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
00289 #endif
00290   }
00291 #endif
00292   if ( obj.isNull() ) // JS disabled
00293     return 0;
00294   return static_cast<KJS::Window*>(obj.imp());
00295 }
00296 
00297 Window *Window::retrieveActive(ExecState *exec)
00298 {
00299   ValueImp *imp = exec->interpreter()->globalObject().imp();
00300   assert( imp );
00301 #ifndef QWS
00302   assert( dynamic_cast<KJS::Window*>(imp) );
00303 #endif
00304   return static_cast<KJS::Window*>(imp);
00305 }
00306 
00307 Value Window::retrieve(KHTMLPart *p)
00308 {
00309   assert(p);
00310   KJSProxy *proxy = KJSProxy::proxy( p );
00311   if (proxy) {
00312 #ifdef KJS_VERBOSE
00313     kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
00314 #endif
00315     return proxy->interpreter()->globalObject(); // the Global object is the "window"
00316   } else {
00317 #ifdef KJS_VERBOSE
00318     kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl;
00319 #endif
00320     return Undefined(); // This can happen with JS disabled on the domain of that window
00321   }
00322 }
00323 
00324 Location *Window::location() const
00325 {
00326   if (!loc)
00327     const_cast<Window*>(this)->loc = new Location(m_part);
00328   return loc;
00329 }
00330 
00331 ObjectImp* Window::frames( ExecState* exec ) const
00332 {
00333   return m_frames ? m_frames :
00334     (const_cast<Window*>(this)->m_frames = new FrameArray(exec,m_part));
00335 }
00336 
00337 // reference our special objects during garbage collection
00338 void Window::mark()
00339 {
00340   ObjectImp::mark();
00341   if (screen && !screen->marked())
00342     screen->mark();
00343   if (history && !history->marked())
00344     history->mark();
00345   if (m_frames && !m_frames->marked())
00346     m_frames->mark();
00347   //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
00348   if (loc && !loc->marked())
00349     loc->mark();
00350 }
00351 
00352 bool Window::hasProperty(ExecState *exec, const UString &p) const
00353 {
00354   if (p == "closed")
00355     return true;
00356 
00357   // we don't want any operations on a closed window
00358   if (m_part.isNull())
00359     return false;
00360 
00361   if (ObjectImp::hasProperty(exec, p))
00362     return true;
00363 
00364   if (Lookup::findEntry(&WindowTable, p))
00365     return true;
00366 
00367   QString q = p.qstring();
00368   if (m_part->findFrame(p.qstring()))
00369     return true;
00370 
00371   // allow shortcuts like 'Image1' instead of document.images.Image1
00372   if (m_part->document().isHTMLDocument()) { // might be XML
00373     DOM::HTMLCollection coll = m_part->htmlDocument().all();
00374     DOM::HTMLElement element = coll.namedItem(q);
00375     if (!element.isNull())
00376       return true;
00377   }
00378 
00379   return false;
00380 }
00381 
00382 UString Window::toString(ExecState *) const
00383 {
00384   return "[object Window]";
00385 }
00386 
00387 Value Window::get(ExecState *exec, const UString &p) const
00388 {
00389 #ifdef KJS_VERBOSE
00390   kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
00391 #endif
00392   if ( p == "closed" )
00393     return Boolean(m_part.isNull());
00394 
00395   // we don't want any operations on a closed window
00396   if (m_part.isNull())
00397     return Undefined();
00398 
00399   // Look for overrides first
00400   Value val = ObjectImp::get(exec, p);
00401   if (!val.isA(UndefinedType)) {
00402     //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
00403     return isSafeScript(exec) ? val : Undefined();
00404   }
00405 
00406   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
00407 
00408   // properties that work on all windows
00409   if (entry) {
00410     switch(entry->value) {
00411     case Closed:
00412       return Boolean( false );
00413     case _Location:
00414       // No isSafeScript test here, we must be able to _set_ location.href (#49819)
00415       return Value(location());
00416     case Frames:
00417       return Value(frames(exec));
00418     case Opener:
00419       if (!m_part->opener())
00420         return Null();    // ### a null Window might be better, but == null
00421       else                // doesn't work yet
00422         return retrieve(m_part->opener());
00423     case Parent:
00424       return retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part);
00425     case _Window:
00426     case Self:
00427       return retrieve(m_part);
00428     case Top: {
00429       KHTMLPart *p = m_part;
00430       while (p->parentPart())
00431         p = p->parentPart();
00432       return retrieve(p);
00433     }
00434     case Alert:
00435     case Confirm:
00436     case Prompt:
00437     case Open:
00438     case Focus:
00439     case Blur:
00440       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00441     default:
00442       break;
00443     }
00444   }
00445 
00446   // properties that only work on safe windows
00447   if (isSafeScript(exec) && entry)
00448   {
00449     //kdDebug(6070) << "token: " << entry->value << endl;
00450     switch( entry->value ) {
00451     case Crypto:
00452       return Undefined(); // ###
00453     case DefaultStatus:
00454       return String(UString(m_part->jsDefaultStatusBarText()));
00455     case Status:
00456       return String(UString(m_part->jsStatusBarText()));
00457     case Document:
00458       if (m_part->document().isNull()) {
00459         kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
00460         m_part->begin();
00461         m_part->write("<HTML><BODY>");
00462         m_part->end();
00463       }
00464       return getDOMNode(exec,m_part->document());
00465     case Node:
00466       return getNodeConstructor(exec);
00467     case Range:
00468       return getRangeConstructor(exec);
00469     case NodeFilter:
00470       return getNodeFilterConstructor(exec);
00471     case DOMException:
00472       return getDOMExceptionConstructor(exec);
00473     case CSSRule:
00474       return getCSSRuleConstructor(exec);
00475     case EventCtor:
00476       return getEventConstructor(exec);
00477     case _History:
00478       return Value(history ? history :
00479                    (const_cast<Window*>(this)->history = new History(exec,m_part)));
00480 
00481     case Event:
00482       if (m_evt)
00483         return getDOMEvent(exec,*m_evt);
00484       else {
00485 #ifdef KJS_VERBOSE
00486         kdWarning(6070) << "window(" << this << "," << m_part->name() << ").event, no event!" << endl;
00487 #endif
00488         return Undefined();
00489       }
00490     case InnerHeight:
00491       if (!m_part->view())
00492         return Undefined();
00493       return Number(m_part->view()->visibleHeight());
00494     case InnerWidth:
00495       if (!m_part->view())
00496         return Undefined();
00497       return Number(m_part->view()->visibleWidth());
00498     case Length:
00499       return Number(m_part->frames().count());
00500     case Name:
00501       return String(m_part->name());
00502     case _Navigator:
00503     case ClientInformation: {
00504       // Store the navigator in the object so we get the same one each time.
00505       Value nav( new Navigator(exec, m_part) );
00506       const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
00507       const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
00508       return nav;
00509     }
00510 #ifdef Q_WS_QWS
00511     case _Konqueror: {
00512       Value k( new Konqueror(exec, m_part) );
00513       const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal);
00514       return k;
00515     }
00516 #endif
00517     case OffscreenBuffering:
00518       return Boolean(true);
00519     case OuterHeight:
00520     case OuterWidth:
00521     {
00522       if (!m_part->widget())
00523         return Number(0);
00524       KWin::Info inf = KWin::info(m_part->widget()->topLevelWidget()->winId());
00525       return Number(entry->value == OuterHeight ?
00526                     inf.geometry.height() : inf.geometry.width());
00527     }
00528     case PageXOffset:
00529       return Number(m_part->view()->contentsX());
00530     case PageYOffset:
00531       return Number(m_part->view()->contentsY());
00532     case Personalbar:
00533       return Undefined(); // ###
00534     case ScreenLeft:
00535     case ScreenX: {
00536       if (!m_part->view())
00537         return Undefined();
00538       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
00539       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
00540     }
00541     case ScreenTop:
00542     case ScreenY: {
00543       if (!m_part->view())
00544         return Undefined();
00545       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
00546       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
00547     }
00548     case ScrollX: {
00549       if (!m_part->view())
00550         return Undefined();
00551       return Number(m_part->view()->contentsX());
00552     }
00553     case ScrollY: {
00554       if (!m_part->view())
00555         return Undefined();
00556       return Number(m_part->view()->contentsY());
00557     }
00558     case Scrollbars:
00559       return Undefined(); // ###
00560     case _Screen:
00561       return Value(screen ? screen :
00562                    (const_cast<Window*>(this)->screen = new Screen(exec)));
00563     case Image:
00564       return Value(new ImageConstructorImp(exec, m_part->document()));
00565     case Option:
00566       return Value(new OptionConstructorImp(exec, m_part->document()));
00567     case Close:
00568     case Scroll: // compatibility
00569     case ScrollBy:
00570     case ScrollTo:
00571     case MoveBy:
00572     case MoveTo:
00573     case ResizeBy:
00574     case ResizeTo:
00575     case AddEventListener:
00576     case RemoveEventListener:
00577       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00578     case SetTimeout:
00579     case ClearTimeout:
00580     case SetInterval:
00581     case ClearInterval:
00582     case Print:
00583       return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
00584     case Onabort:
00585       return getListener(exec,DOM::EventImpl::ABORT_EVENT);
00586     case Onblur:
00587       return getListener(exec,DOM::EventImpl::BLUR_EVENT);
00588     case Onchange:
00589       return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
00590     case Onclick:
00591       return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
00592     case Ondblclick:
00593       return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
00594     case Ondragdrop:
00595       return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
00596     case Onerror:
00597       return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
00598     case Onfocus:
00599       return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
00600     case Onkeydown:
00601       return getListener(exec,DOM::EventImpl::KHTML_KEYDOWN_EVENT);
00602     case Onkeypress:
00603       return getListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT);
00604     case Onkeyup:
00605       return getListener(exec,DOM::EventImpl::KHTML_KEYUP_EVENT);
00606     case Onload:
00607       return getListener(exec,DOM::EventImpl::LOAD_EVENT);
00608     case Onmousedown:
00609       return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
00610     case Onmousemove:
00611       return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
00612     case Onmouseout:
00613       return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
00614     case Onmouseover:
00615       return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
00616     case Onmouseup:
00617       return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
00618     case Onmove:
00619       return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
00620     case Onreset:
00621       return getListener(exec,DOM::EventImpl::RESET_EVENT);
00622     case Onresize:
00623       return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
00624     case Onselect:
00625       return getListener(exec,DOM::EventImpl::SELECT_EVENT);
00626     case Onsubmit:
00627       return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
00628     case Onunload:
00629       return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
00630     }
00631   }
00632   KHTMLPart *kp = m_part->findFrame( p.qstring() );
00633   if (kp)
00634     return retrieve(kp);
00635 
00636   // allow shortcuts like 'Image1' instead of document.images.Image1
00637   if (isSafeScript(exec) &&
00638       m_part->document().isHTMLDocument()) { // might be XML
00639     DOM::HTMLCollection coll = m_part->htmlDocument().all();
00640     DOM::HTMLElement element = coll.namedItem(p.string());
00641     if (!element.isNull()) {
00642       return getDOMNode(exec,element);
00643     }
00644   }
00645 
00646 #if 0 
00647   // give access to functions (and variables ?) from parent frameset
00648   if (m_part->parentPart())
00649   {
00650     Object parentObject = Object::dynamicCast( retrieve(m_part->parentPart()) );
00651     if ( !parentObject.isNull() )
00652     {
00653       Value ret = parentObject.get(exec,p);
00654       if (ret.type() != UndefinedType ) {
00655 #ifdef KJS_VERBOSE
00656         kdDebug(6070) << "Window::get property " << p.qstring() << " found in parent part" << endl;
00657 #endif
00658         return ret;
00659       }
00660     }
00661   }
00662 #endif
00663 
00664   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
00665   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
00666 #ifdef KJS_VERBOSE
00667   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
00668 #endif
00669   return Undefined();
00670 }
00671 
00672 void Window::put(ExecState* exec, const UString &propertyName, const Value &value, int attr)
00673 {
00674   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
00675   // If yes, save time and jump directly to ObjectImp.
00676   if ( (attr != None && attr != DontDelete)
00677        // Same thing if we have a local override (e.g. "var location")
00678        || ( ObjectImp::getDirect(propertyName) && isSafeScript(exec)) )
00679   {
00680     ObjectImp::put( exec, propertyName, value, attr );
00681     return;
00682   }
00683 
00684   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
00685   if (entry)
00686   {
00687 #ifdef KJS_VERBOSE
00688     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
00689 #endif
00690     switch( entry->value ) {
00691     case Status: {
00692       if ( isSafeScript(exec) ) {
00693         String s = value.toString(exec);
00694         m_part->setJSStatusBarText(s.value().qstring());
00695       }
00696       return;
00697     }
00698     case DefaultStatus: {
00699       if ( isSafeScript(exec) ) {
00700         String s = value.toString(exec);
00701         m_part->setJSDefaultStatusBarText(s.value().qstring());
00702       }
00703       return;
00704     }
00705     case _Location:
00706       goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/);
00707       return;
00708     case Onabort:
00709       if (isSafeScript(exec))
00710         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
00711       return;
00712     case Onblur:
00713       if (isSafeScript(exec))
00714         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
00715       return;
00716     case Onchange:
00717       if (isSafeScript(exec))
00718         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
00719       return;
00720     case Onclick:
00721       if (isSafeScript(exec))
00722         setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
00723       return;
00724     case Ondblclick:
00725       if (isSafeScript(exec))
00726         setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
00727       return;
00728     case Ondragdrop:
00729       if (isSafeScript(exec))
00730         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
00731       return;
00732     case Onerror:
00733       if (isSafeScript(exec))
00734         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
00735       return;
00736     case Onfocus:
00737       if (isSafeScript(exec))
00738         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
00739       return;
00740     case Onkeydown:
00741       if (isSafeScript(exec))
00742         setListener(exec,DOM::EventImpl::KHTML_KEYDOWN_EVENT,value);
00743       return;
00744     case Onkeypress:
00745       if (isSafeScript(exec))
00746         setListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT,value);
00747       return;
00748     case Onkeyup:
00749       if (isSafeScript(exec))
00750         setListener(exec,DOM::EventImpl::KHTML_KEYUP_EVENT,value);
00751       return;
00752     case Onload:
00753       if (isSafeScript(exec))
00754         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
00755       return;
00756     case Onmousedown:
00757       if (isSafeScript(exec))
00758         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
00759       return;
00760     case Onmousemove:
00761       if (isSafeScript(exec))
00762         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
00763       return;
00764     case Onmouseout:
00765       if (isSafeScript(exec))
00766         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
00767       return;
00768     case Onmouseover:
00769       if (isSafeScript(exec))
00770         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
00771       return;
00772     case Onmouseup:
00773       if (isSafeScript(exec))
00774         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
00775       return;
00776     case Onmove:
00777       if (isSafeScript(exec))
00778         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
00779       return;
00780     case Onreset:
00781       if (isSafeScript(exec))
00782         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
00783       return;
00784     case Onresize:
00785       if (isSafeScript(exec))
00786         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
00787       return;
00788     case Onselect:
00789       if (isSafeScript(exec))
00790         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
00791       return;
00792     case Onsubmit:
00793       if (isSafeScript(exec))
00794         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
00795       return;
00796     case Onunload:
00797       if (isSafeScript(exec))
00798         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
00799       return;
00800     case Name:
00801       if (isSafeScript(exec))
00802         m_part->setName( value.toString(exec).qstring().local8Bit().data() );
00803       return;
00804     default:
00805       break;
00806     }
00807   }
00808   if (isSafeScript(exec)) {
00809     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
00810     ObjectImp::put(exec, propertyName, value, attr);
00811   }
00812 }
00813 
00814 bool Window::toBoolean(ExecState *) const
00815 {
00816   return !m_part.isNull();
00817 }
00818 
00819 int Window::installTimeout(const UString &handler, int t, bool singleShot)
00820 {
00821   return winq->installTimeout(handler, t, singleShot);
00822 }
00823 
00824 void Window::clearTimeout(int timerId)
00825 {
00826   winq->clearTimeout(timerId);
00827 }
00828 
00829 void Window::scheduleClose()
00830 {
00831   kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
00832   Q_ASSERT(winq);
00833   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
00834 }
00835 
00836 void Window::closeNow()
00837 {
00838   if (!m_part.isNull())
00839   {
00840     //kdDebug(6070) << k_funcinfo << " -> closing window" << endl;
00841     // We want to make sure that window.open won't find this part by name.
00842     m_part->setName( 0 );
00843     m_part->deleteLater();
00844     m_part = 0;
00845   } else
00846     kdDebug(6070) << k_funcinfo << "part is deleted already" << endl;
00847 }
00848 
00849 void Window::afterScriptExecution()
00850 {
00851   DOM::DocumentImpl::updateDocumentsRendering();
00852   QValueList<DelayedAction> delayedActions = m_delayed;
00853   m_delayed.clear();
00854   QValueList<DelayedAction>::Iterator it = delayedActions.begin();
00855   for ( ; it != delayedActions.end() ; ++it )
00856   {
00857     switch ((*it).actionId) {
00858     case DelayedClose:
00859       scheduleClose();
00860       return; // stop here, in case of multiple actions
00861     case DelayedGoHistory:
00862       goHistory( (*it).param.toInt() );
00863       break;
00864     };
00865   }
00866 }
00867 
00868 bool Window::isSafeScript(ExecState *exec) const
00869 {
00870   if (m_part.isNull()) { // part deleted ? can't grant access
00871     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
00872     return false;
00873   }
00874   KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->interpreter() )->part();
00875   if (!activePart) {
00876     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
00877     return false;
00878   }
00879   if ( activePart == m_part ) // Not calling from another frame, no problem.
00880     return true;
00881 
00882   if ( m_part->document().isNull() )
00883     return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
00884 
00885   DOM::HTMLDocument thisDocument = m_part->htmlDocument();
00886   if ( thisDocument.isNull() ) {
00887     kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl;
00888     return false;
00889   }
00890 
00891   DOM::HTMLDocument actDocument = activePart->htmlDocument();
00892   if ( actDocument.isNull() ) {
00893     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
00894     return false;
00895   }
00896   DOM::DOMString actDomain = actDocument.domain();
00897   DOM::DOMString thisDomain = thisDocument.domain();
00898 
00899   if ( actDomain == thisDomain ) {
00900     //kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl;
00901     return true;
00902   }
00903 
00904   kdWarning(6070) << "JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
00905   // TODO after 3.1: throw security exception (exec->setException())
00906   return false;
00907 }
00908 
00909 void Window::setListener(ExecState *exec, int eventId, Value func)
00910 {
00911   if (!isSafeScript(exec))
00912     return;
00913   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
00914   if (!doc)
00915     return;
00916 
00917   doc->setWindowEventListener(eventId,getJSEventListener(func,true));
00918 }
00919 
00920 Value Window::getListener(ExecState *exec, int eventId) const
00921 {
00922   if (!isSafeScript(exec))
00923     return Undefined();
00924   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
00925   if (!doc)
00926     return Undefined();
00927 
00928   DOM::EventListener *listener = doc->getWindowEventListener(eventId);
00929   if (listener)
00930     return static_cast<JSEventListener*>(listener)->listenerObj();
00931   else
00932     return Null();
00933 }
00934 
00935 
00936 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
00937 {
00938   // This function is so hot that it's worth coding it directly with imps.
00939   if (val.type() != ObjectType)
00940     return 0;
00941   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
00942 
00943   QPtrListIterator<JSEventListener> it(jsEventListeners);
00944   for (; it.current(); ++it)
00945     if (it.current()->listenerObjImp() == listenerObject)
00946       return it.current();
00947 
00948   // Note that the JSEventListener constructor adds it to our jsEventListeners list
00949   return new JSEventListener(Object(listenerObject), Object(this), html);
00950 }
00951 
00952 void Window::clear( ExecState *exec )
00953 {
00954   kdDebug(6070) << "Window::clear " << this << endl;
00955   delete winq;
00956   winq = 0L;
00957   // Get rid of everything, those user vars could hold references to DOM nodes
00958   deleteAllProperties( exec );
00959 
00960   // Break the dependency between the listeners and their object
00961   QPtrListIterator<JSEventListener> it(jsEventListeners);
00962   for (; it.current(); ++it)
00963     it.current()->clear();
00964   // Forget about the listeners (the DOM::NodeImpls will delete them)
00965   jsEventListeners.clear();
00966 
00967   if (!m_part.isNull()) {
00968     KJSProxy* proxy = KJSProxy::proxy( m_part );
00969     if (proxy) // i.e. JS not disabled
00970     {
00971       winq = new WindowQObject(this);
00972       // Now recreate a working global object for the next URL that will use us
00973       KJS::Interpreter *interpreter = proxy->interpreter();
00974       interpreter->initGlobalObject();
00975     }
00976   }
00977 }
00978 
00979 void Window::setCurrentEvent( DOM::Event *evt )
00980 {
00981   m_evt = evt;
00982   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
00983 }
00984 
00985 void Window::goURL(ExecState* exec, const QString& url, bool lockHistory)
00986 {
00987   Window* active = Window::retrieveActive(exec);
00988   // Complete the URL using the "active part" (running interpreter)
00989   if (active->part()) {
00990     QString dstUrl = active->part()->htmlDocument().completeURL(url).string();
00991     kdDebug() << "Window::goURL dstUrl=" << dstUrl << " m_part->url()=" << m_part->url().url() << endl;
00992     // Check if the URL is the current one. No [infinite] redirect in that case.
00993     if ( m_part->url().cmp( KURL(dstUrl), true ) )
00994         return;
00995 
00996     // check if we're allowed to inject javascript
00997     // SYNC check with khtml_part.cpp::slotRedirect!
00998     if ( isSafeScript(exec) ||
00999             dstUrl.find(QString::fromLatin1("javascript:"), 0, false) != 0 )
01000       m_part->scheduleRedirection(-1,
01001                                 dstUrl,
01002                                   lockHistory);
01003   }
01004 }
01005 
01006 void Window::delayedGoHistory( int steps )
01007 {
01008     m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
01009 }
01010 
01011 void Window::goHistory( int steps )
01012 {
01013   KParts::BrowserExtension *ext = m_part->browserExtension();
01014   if(!ext)
01015     return;
01016   KParts::BrowserInterface *iface = ext->browserInterface();
01017 
01018   if ( !iface )
01019     return;
01020 
01021   iface->callMethod( "goHistory(int)", steps );
01022   //emit ext->goHistory(steps);
01023 }
01024 
01025 void KJS::Window::resizeTo(QWidget* tl, int width, int height)
01026 {
01027   // Security check: within desktop limits and bigger than 100x100 (per spec)
01028   if ( width < 100 || height < 100 ) {
01029     kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl;
01030     return;
01031   }
01032   QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
01033   if ( width > sg.width() || height > sg.height() ) {
01034     kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl;
01035     return;
01036   }
01037 
01038   // Take into account the window frame - so that (width,height) is the external window size
01039   // ### (is that correct? for window.open it's the size of the HTML area...)
01040   int deltaWidth = tl->frameGeometry().width() - tl->width();
01041   int deltaHeight = tl->frameGeometry().height() - tl->height();
01042 
01043   kdDebug() << "resizing to " << width - deltaWidth << "x" << height - deltaHeight << endl;
01044 
01045   tl->resize( width - deltaWidth, height - deltaHeight );
01046 
01047   // If the window is out of the desktop, move it up/left
01048   // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
01049   int right = tl->x() + tl->frameGeometry().width();
01050   int bottom = tl->y() + tl->frameGeometry().height();
01051   int moveByX = 0;
01052   int moveByY = 0;
01053   if ( right > sg.right() )
01054     moveByX = - right + sg.right(); // always <0
01055   if ( bottom > sg.bottom() )
01056     moveByY = - bottom + sg.bottom(); // always <0
01057   if ( moveByX || moveByY )
01058     tl->move( tl->x() + moveByX , tl->y() + moveByY );
01059 }
01060 
01061 Value Window::openWindow(ExecState *exec, const List& args)
01062 {
01063   KHTMLView *widget = m_part->view();
01064   Value v = args[0];
01065   UString s = v.toString(exec);
01066   QString str = s.qstring();
01067 
01068   KConfig *config = new KConfig( "konquerorrc" );
01069   config->setGroup( "Java/JavaScript Settings" );
01070   int policy = config->readUnsignedNumEntry(  "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
01071   delete config;
01072   if (  policy == 1 ) {
01073     if ( KMessageBox::questionYesNo(widget,
01074                                     i18n( "This site is trying to open up a new browser "
01075                                           "window using JavaScript.\n"
01076                                           "Do you want to allow this?" ),
01077                                     i18n( "Confirmation: JavaScript Popup" ) ) == KMessageBox::Yes )
01078       policy = 0;
01079   } else if ( policy == 3 )
01080   {
01081     // window.open disabled unless from a key/mouse event
01082     if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed())
01083       policy = 0;
01084   }
01085   if ( policy != 0 ) {
01086     return Undefined();
01087   } else {
01088     KParts::WindowArgs winargs;
01089 
01090     // scan feature argument
01091     QString features;
01092     if (args.size()>2) {
01093       features = args[2].toString(exec).qstring();
01094       // specifying window params means false defaults
01095       winargs.menuBarVisible = false;
01096       winargs.toolBarsVisible = false;
01097       winargs.statusBarVisible = false;
01098       QStringList flist = QStringList::split(',', features);
01099       QStringList::ConstIterator it = flist.begin();
01100       while (it != flist.end()) {
01101         QString s = *it++;
01102         QString key, val;
01103         int pos = s.find('=');
01104         if (pos >= 0) {
01105           key = s.left(pos).stripWhiteSpace().lower();
01106           val = s.mid(pos + 1).stripWhiteSpace().lower();
01107 
01108           int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
01109 
01110           QRect screen = QApplication::desktop()->screenGeometry(scnum);
01111           if (key == "left" || key == "screenx") {
01112             winargs.x = val.toInt() + screen.x();
01113             if (winargs.x < screen.x() || winargs.x > screen.right())
01114               winargs.x = screen.x(); // only safe choice until size is determined
01115           } else if (key == "top" || key == "screeny") {
01116             winargs.y = val.toInt() + screen.y();
01117             if (winargs.y < screen.y() || winargs.y > screen.bottom())
01118               winargs.y = screen.y(); // only safe choice until size is determined
01119           } else if (key == "height") {
01120             winargs.height = val.toInt() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01121             if (winargs.height > screen.height())  // should actually check workspace
01122               winargs.height = screen.height();
01123             if (winargs.height < 100)
01124               winargs.height = 100;
01125           } else if (key == "width") {
01126             winargs.width = val.toInt() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
01127             if (winargs.width > screen.width())    // should actually check workspace
01128               winargs.width = screen.width();
01129             if (winargs.width < 100)
01130               winargs.width = 100;
01131           } else {
01132             goto boolargs;
01133           }
01134           continue;
01135         } else {
01136           // leaving away the value gives true
01137           key = s.stripWhiteSpace().lower();
01138           val = "1";
01139         }
01140       boolargs:
01141         if (key == "menubar")
01142           winargs.menuBarVisible = (val == "1" || val == "yes");
01143         else if (key == "toolbar")
01144           winargs.toolBarsVisible = (val == "1" || val == "yes");
01145         else if (key == "location")  // ### missing in WindowArgs
01146           winargs.toolBarsVisible = (val == "1" || val == "yes");
01147         else if (key == "status" || key == "statusbar")
01148           winargs.statusBarVisible = (val == "1" || val == "yes");
01149         else if (key == "resizable")
01150           winargs.resizable = (val == "1" || val == "yes");
01151         else if (key == "fullscreen")
01152           winargs.fullscreen = (val == "1" || val == "yes");
01153       }
01154     }
01155 
01156     // prepare arguments
01157     KURL url;
01158     if (!str.isEmpty())
01159     {
01160       KHTMLPart* p = Window::retrieveActive(exec)->m_part;
01161       if ( p )
01162         url = p->htmlDocument().completeURL(str).string();
01163       if ( !p ||
01164            !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
01165           return Undefined();
01166     }
01167 
01168     KParts::URLArgs uargs;
01169     KHTMLPart *p = m_part;
01170     uargs.frameName = args.size() > 1 ?
01171                       args[1].toString(exec).qstring()
01172                       : QString("_blank");
01173     if ( uargs.frameName.lower() == "_top" )
01174     {
01175       while ( p->parentPart() )
01176         p = p->parentPart();
01177       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01178       return Window::retrieve(p);
01179     }
01180     if ( uargs.frameName.lower() == "_parent" )
01181     {
01182       if ( p->parentPart() )
01183         p = p->parentPart();
01184       Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
01185       return Window::retrieve(p);
01186     }
01187     uargs.serviceType = "text/html";
01188 
01189     // request window (new or existing if framename is set)
01190     KParts::ReadOnlyPart *newPart = 0L;
01191     emit p->browserExtension()->createNewWindow("", uargs,winargs,newPart);
01192     if (newPart && newPart->inherits("KHTMLPart")) {
01193       KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
01194       //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
01195       khtmlpart->setOpener(p);
01196       khtmlpart->setOpenedByJS(true);
01197       if (khtmlpart->document().isNull()) {
01198         khtmlpart->begin();
01199         khtmlpart->write("<HTML><BODY>");
01200         khtmlpart->end();
01201         if ( p->docImpl() ) {
01202           kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
01203           khtmlpart->docImpl()->setDomain( p->docImpl()->domain());
01204           khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
01205         }
01206       }
01207       uargs.serviceType = QString::null;
01208       if (uargs.frameName.lower() == "_blank")
01209         uargs.frameName = QString::null;
01210       if (!url.isEmpty())
01211         emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
01212       return Window::retrieve(khtmlpart); // global object
01213     } else
01214       return Undefined();
01215   }
01216 }
01217 
01218 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01219 {
01220   KJS_CHECK_THIS( Window, thisObj );
01221   Window *window = static_cast<Window *>(thisObj.imp());
01222   QString str, str2;
01223 
01224   KHTMLPart *part = window->m_part;
01225   if (!part)
01226     return Undefined();
01227 
01228   KHTMLView *widget = part->view();
01229   Value v = args[0];
01230   UString s = v.toString(exec);
01231   str = s.qstring();
01232 
01233   // functions that work everywhere
01234   switch(id) {
01235   case Window::Alert:
01236     if (!widget->dialogsAllowed())
01237       return Undefined();
01238     part->xmlDocImpl()->updateRendering();
01239     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
01240     return Undefined();
01241   case Window::Confirm:
01242     if (!widget->dialogsAllowed())
01243       return Undefined();
01244     part->xmlDocImpl()->updateRendering();
01245     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
01246                                                 i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
01247   case Window::Prompt:
01248     part->xmlDocImpl()->updateRendering();
01249     bool ok;
01250     if (args.size() >= 2)
01251       str2 = KLineEditDlg::getText(i18n("Konqueror: Prompt"),
01252                                    QStyleSheet::convertFromPlainText(str),
01253                                    args[1].toString(exec).qstring(), &ok);
01254     else
01255       str2 = KLineEditDlg::getText(i18n("Konqueror: Prompt"),
01256                                    QStyleSheet::convertFromPlainText(str),
01257                                    QString::null, &ok);
01258     if ( ok )
01259         return String(str2);
01260     else
01261         return Null();
01262   case Window::Open:
01263     return window->openWindow(exec, args);
01264   case Window::Focus: {
01265     if(widget) {
01266       widget->topLevelWidget()->raise();
01267       widget->setActiveWindow();
01268     }
01269     return Undefined();
01270   }
01271   case Window::Blur:
01272     // TODO
01273     return Undefined();
01274   };
01275 
01276 
01277   // now unsafe functions..
01278   if (!window->isSafeScript(exec))
01279     return Undefined();
01280 
01281   switch (id) {
01282   case Window::Scroll:
01283   case Window::ScrollBy:
01284     if(args.size() == 2 && widget)
01285       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
01286     return Undefined();
01287   case Window::ScrollTo:
01288     if(args.size() == 2 && widget)
01289       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
01290     return Undefined();
01291   case Window::MoveBy: {
01292     if(args.size() == 2 && widget)
01293     {
01294       QWidget * tl = widget->topLevelWidget();
01295           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
01296       QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
01297       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01298       if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
01299            dest.x()+tl->width() <= sg.width()+sg.x() &&
01300            dest.y()+tl->height() <= sg.height()+sg.y() )
01301         tl->move( dest );
01302     }
01303     return Undefined();
01304   }
01305   case Window::MoveTo: {
01306     if(args.size() == 2 && widget)
01307     {
01308       QWidget * tl = widget->topLevelWidget();
01309           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
01310       QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
01311       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
01312       if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
01313            dest.x()+tl->width() <= sg.width()+sg.x() &&
01314            dest.y()+tl->height() <= sg.height()+sg.y() )
01315         tl->move( dest );
01316     }
01317     return Undefined();
01318   }
01319   case Window::ResizeBy: {
01320     if(args.size() == 2 && widget)
01321     {
01322       QWidget * tl = widget->topLevelWidget();
01323       window->resizeTo( tl, tl->width() + args[0].toInt32(exec), tl->height() + args[1].toInt32(exec) );
01324     }
01325     return Undefined();
01326   }
01327   case Window::ResizeTo: {
01328     if(args.size() == 2 && widget)
01329     {
01330       QWidget * tl = widget->topLevelWidget();
01331       window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
01332     }
01333     return Undefined();
01334   }
01335   case Window::SetTimeout:
01336     if (args.size() == 2 && v.isA(StringType)) {
01337       int i = args[1].toInt32(exec);
01338       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
01339       return Number(r);
01340     }
01341     else if (args.size() >= 2 && v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
01342       Value func = args[0];
01343       int i = args[1].toInt32(exec);
01344 #if 0
01345 //  ### TODO
01346       List *funcArgs = args.copy();
01347       funcArgs->removeFirst(); // all args after 2 go to the function
01348       funcArgs->removeFirst();
01349 #endif
01350       if ( args.size() > 2 )
01351         kdWarning(6070) << "setTimeout(more than 2 args) is not fully implemented!" << endl;
01352       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
01353       return Number(r);
01354     }
01355     else
01356       return Undefined();
01357   case Window::SetInterval:
01358     if (args.size() >= 2 && v.isA(StringType)) {
01359       int i = args[1].toInt32(exec);
01360       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
01361       return Number(r);
01362     }
01363     else if (args.size() >= 2 && !Object::dynamicCast(v).isNull() &&
01364              Object::dynamicCast(v).implementsCall()) {
01365       Value func = args[0];
01366       int i = args[1].toInt32(exec);
01367 #if 0
01368 // ### TODO
01369       List *funcArgs = args.copy();
01370       funcArgs->removeFirst(); // all args after 2 go to the function
01371       funcArgs->removeFirst();
01372 #endif
01373       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
01374       return Number(r);
01375     }
01376     else
01377       return Undefined();
01378   case Window::ClearTimeout:
01379   case Window::ClearInterval:
01380     (const_cast<Window*>(window))->clearTimeout(v.toInt32(exec));
01381     return Undefined();
01382  case Window::Blur:
01383     // TODO
01384     return Undefined();
01385   case Window::Close: {
01386     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
01387        The close method closes only windows opened by JavaScript using the open method.
01388        If you attempt to close any other window, a confirm is generated, which
01389        lets the user choose whether the window closes.
01390        This is a security feature to prevent "mail bombs" containing self.close().
01391        However, if the window has only one document (the current one) in its
01392        session history, the close is allowed without any confirm. This is a
01393        special case for one-off windows that need to open other windows and
01394        then dispose of themselves.
01395     */
01396     bool doClose = false;
01397     if (!part->openedByJS())
01398     {
01399       // To conform to the SPEC, we only ask if the window
01400       // has more than one entry in the history (NS does that too).
01401       History history(exec,part);
01402       if ( history.get( exec, "length" ).toInt32(exec) <= 1 ||
01403            KMessageBox::questionYesNo( window->part()->widget(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes )
01404         doClose = true;
01405     }
01406     else
01407       doClose = true;
01408 
01409     if (doClose)
01410     {
01411       // If this is the current window (the one the interpreter runs in),
01412       // then schedule a delayed close (so that the script terminates first).
01413       // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
01414       if ( Window::retrieveActive(exec) == window ) {
01415         if (widget) {
01416           // quit all dialogs of this view
01417           // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
01418           widget->closeChildDialogs();
01419         }
01420         //kdDebug() << "scheduling delayed close"  << endl;
01421         // We'll close the window at the end of the script execution
01422         Window* w = const_cast<Window*>(window);
01423         w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
01424       } else {
01425         //kdDebug() << "closing NOW"  << endl;
01426         (const_cast<Window*>(window))->closeNow();
01427       }
01428     }
01429     return Undefined();
01430   }
01431   case Window::Print:
01432     if ( widget ) {
01433       // ### TODO emit onbeforeprint event
01434       widget->print();
01435       // ### TODO emit onafterprint event
01436     }
01437   case Window::AddEventListener: {
01438         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01439         DOM::Document doc = part->document();
01440         if (doc.isHTMLDocument()) {
01441             DOM::HTMLDocument htmlDoc = doc;
01442             htmlDoc.body().addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01443         }
01444         else
01445             doc.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01446         return Undefined();
01447     }
01448   case Window::RemoveEventListener: {
01449         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
01450         DOM::Document doc = part->document();
01451         if (doc.isHTMLDocument()) {
01452             DOM::HTMLDocument htmlDoc = doc;
01453             htmlDoc.body().removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01454         }
01455         else
01456             doc.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec));
01457         return Undefined();
01458     }
01459     break;
01460   }
01461   return Undefined();
01462 }
01463 
01465 
01466 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
01467 {
01468   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
01469   func = _func;
01470   args = _args;
01471   isFunction = true;
01472   singleShot = _singleShot;
01473 }
01474 
01475 ScheduledAction::ScheduledAction(QString _code, bool _singleShot)
01476 {
01477   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
01478   //func = 0;
01479   //args = 0;
01480   code = _code;
01481   isFunction = false;
01482   singleShot = _singleShot;
01483 }
01484 
01485 void ScheduledAction::execute(Window *window)
01486 {
01487   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
01488 
01489   interpreter->setProcessingTimerCallback(true);
01490 
01491   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
01492   if (isFunction) {
01493     if (func.implementsCall()) {
01494       // #### check this
01495       Q_ASSERT( window->m_part );
01496       if ( window->m_part )
01497       {
01498         KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
01499         ExecState *exec = interpreter->globalExec();
01500         Q_ASSERT( window == interpreter->globalObject().imp() );
01501         Object obj( window );
01502         func.call(exec,obj,args); // note that call() creates its own execution state for the func call
01503       }
01504     }
01505   }
01506   else {
01507     window->m_part->executeScript(code);
01508   }
01509 
01510   interpreter->setProcessingTimerCallback(false);
01511 }
01512 
01513 ScheduledAction::~ScheduledAction()
01514 {
01515   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
01516 }
01517 
01519 
01520 WindowQObject::WindowQObject(Window *w)
01521   : parent(w)
01522 {
01523   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
01524   part = parent->m_part;
01525   if ( !part )
01526       kdWarning(6070) << "null part in " << k_funcinfo << endl;
01527   else
01528       connect( part, SIGNAL( destroyed() ),
01529                this, SLOT( parentDestroyed() ) );
01530 }
01531 
01532 WindowQObject::~WindowQObject()
01533 {
01534   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
01535   parentDestroyed(); // reuse same code
01536 }
01537 
01538 void WindowQObject::parentDestroyed()
01539 {
01540   //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
01541   killTimers();
01542   QMapIterator<int,ScheduledAction*> it;
01543   for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
01544     ScheduledAction *action = *it;
01545     //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
01546     delete action;
01547   }
01548   scheduledActions.clear();
01549 }
01550 
01551 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
01552 {
01553   //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << " milliseconds=" << t << endl;
01554   if (t < 10) t = 10;
01555   int id = startTimer(t);
01556   ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
01557   scheduledActions.insert(id, action);
01558   //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
01559   return id;
01560 }
01561 
01562 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
01563 {
01564   Object objFunc = Object::dynamicCast( func );
01565   if (t < 10) t = 10;
01566   int id = startTimer(t);
01567   scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
01568   return id;
01569 }
01570 
01571 void WindowQObject::clearTimeout(int timerId, bool delAction)
01572 {
01573   //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
01574   killTimer(timerId);
01575   if (delAction) {
01576     QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
01577     if (it != scheduledActions.end()) {
01578       ScheduledAction *action = *it;
01579       scheduledActions.remove(it);
01580       delete action;
01581     }
01582   }
01583 }
01584 
01585 void WindowQObject::timerEvent(QTimerEvent *e)
01586 {
01587   QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
01588   if (it != scheduledActions.end()) {
01589     ScheduledAction *action = *it;
01590     bool singleShot = action->singleShot;
01591     //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
01592 
01593     // remove single shots installed by setTimeout()
01594     if (singleShot)
01595     {
01596       clearTimeout(e->timerId(),false);
01597       scheduledActions.remove(it);
01598     }
01599     if (!parent->part().isNull())
01600       action->execute(parent);
01601 
01602     // It is important to test singleShot and not action->singleShot here - the
01603     // action could have been deleted already if not single shot and if the
01604     // JS code called by execute() calls clearTimeout().
01605     if (singleShot)
01606       delete action;
01607   } else
01608     kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
01609                     << " not found (" << scheduledActions.count() << " actions in map)" << endl;
01610 }
01611 
01612 void WindowQObject::timeoutClose()
01613 {
01614   parent->closeNow();
01615 }
01616 
01617 Value FrameArray::get(ExecState *exec, const UString &p) const
01618 {
01619 #ifdef KJS_VERBOSE
01620   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
01621 #endif
01622   if (part.isNull())
01623     return Undefined();
01624 
01625   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
01626   int len = frames.count();
01627   if (p == "length")
01628     return Number(len);
01629   else if (p== "location") // non-standard property, but works in NS and IE
01630   {
01631     Object obj = Object::dynamicCast( Window::retrieve( part ) );
01632     if ( !obj.isNull() )
01633       return obj.get( exec, "location" );
01634     return Undefined();
01635   }
01636 
01637   // check for the name or number
01638   KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
01639   if (!frame) {
01640     int i = (int)p.toDouble();
01641     if (i >= 0 && i < len)
01642       frame = frames.at(i);
01643   }
01644 
01645   // we are potentially fetching a reference to a another Window object here.
01646   // i.e. we may be accessing objects from another interpreter instance.
01647   // Therefore we have to be a bit careful with memory managment.
01648   if (frame && frame->inherits("KHTMLPart")) {
01649     KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
01650     return Window::retrieve(khtml);
01651   }
01652 
01653   return ObjectImp::get(exec, p);
01654 }
01655 
01657 
01658 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
01659 /*
01660 @begin LocationTable 11
01661   hash          Location::Hash          DontDelete
01662   host          Location::Host          DontDelete
01663   hostname      Location::Hostname      DontDelete
01664   href          Location::Href          DontDelete
01665   pathname      Location::Pathname      DontDelete
01666   port          Location::Port          DontDelete
01667   protocol      Location::Protocol      DontDelete
01668   search        Location::Search        DontDelete
01669   [[==]]        Location::EqualEqual    DontDelete|ReadOnly
01670   assign        Location::Assign        DontDelete|Function 1
01671   toString      Location::ToString      DontDelete|Function 0
01672   replace       Location::Replace       DontDelete|Function 1
01673   reload        Location::Reload        DontDelete|Function 0
01674 @end
01675 */
01676 IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
01677 Location::Location(KHTMLPart *p) : m_part(p)
01678 {
01679   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
01680 }
01681 
01682 Location::~Location()
01683 {
01684   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
01685 }
01686 
01687 Value Location::get(ExecState *exec, const UString &p) const
01688 {
01689 #ifdef KJS_VERBOSE
01690   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
01691 #endif
01692 
01693   if (m_part.isNull())
01694     return Undefined();
01695 
01696   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
01697 
01698   // properties that work on all Location objects
01699   if ( entry && entry->value == Replace )
01700       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
01701 
01702   // XSS check
01703   const Window* window = Window::retrieveWindow( m_part );
01704   if ( !window || !window->isSafeScript(exec) )
01705     return Undefined();
01706 
01707   KURL url = m_part->url();
01708   if (entry)
01709     switch (entry->value) {
01710     case Hash:
01711       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
01712     case Host: {
01713       UString str = url.host();
01714       if (url.port())
01715         str += ":" + QString::number((int)url.port());
01716       return String(str);
01717       // Note: this is the IE spec. The NS spec swaps the two, it says
01718       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
01719       // Bleh.
01720     }
01721     case Hostname:
01722       return String( url.host() );
01723     case Href:
01724       if (!url.hasPath())
01725         return String( url.prettyURL()+"/" );
01726       else
01727         return String( url.prettyURL() );
01728     case Pathname:
01729       return String( url.path().isEmpty() ? QString("/") : url.path() );
01730     case Port:
01731       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
01732     case Protocol:
01733       return String( url.protocol()+":" );
01734     case Search:
01735       return String( url.query() );
01736     case EqualEqual: // [[==]]
01737       return String(toString(exec));
01738     case ToString:
01739       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
01740     }
01741   // Look for overrides
01742   ValueImp * val = ObjectImp::getDirect(p);
01743   if (val)
01744     return Value(val);
01745   if (entry && (entry->attr & Function))
01746     return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
01747 
01748   return Undefined();
01749 }
01750 
01751 void Location::put(ExecState *exec, const UString &p, const Value &v, int attr)
01752 {
01753 #ifdef KJS_VERBOSE
01754   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
01755 #endif
01756   if (m_part.isNull())
01757     return;
01758 
01759   // XSS check
01760   const Window* window = Window::retrieveWindow( m_part );
01761   if ( !window || !window->isSafeScript(exec) )
01762     return;
01763 
01764   QString str = v.toString(exec).qstring();
01765   KURL url = m_part->url();
01766   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
01767   if (entry)
01768     switch (entry->value) {
01769     case Href: {
01770       KHTMLPart* p = Window::retrieveActive(exec)->part();
01771       if ( p )
01772         url = p->htmlDocument().completeURL( str ).string();
01773       else
01774         url = str;
01775       break;
01776     }
01777     case Hash:
01778       // when the hash is already the same ignore it
01779       if (str == url.ref()) return;
01780       url.setRef(str);
01781       break;
01782     case Host: {
01783       QString host = str.left(str.find(":"));
01784       QString port = str.mid(str.find(":")+1);
01785       url.setHost(host);
01786       url.setPort(port.toUInt());
01787       break;
01788     }
01789     case Hostname:
01790       url.setHost(str);
01791       break;
01792     case Pathname:
01793       url.setPath(str);
01794       break;
01795     case Port:
01796       url.setPort(str.toUInt());
01797       break;
01798     case Protocol:
01799       url.setProtocol(str);
01800       break;
01801     case Search:
01802       url.setQuery(str);
01803       break;
01804     }
01805   else {
01806     ObjectImp::put(exec, p, v, attr);
01807     return;
01808   }
01809 
01810   Window::retrieveWindow(m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
01811 }
01812 
01813 Value Location::toPrimitive(ExecState *exec, Type) const
01814 {
01815   Window* window = Window::retrieveWindow( m_part );
01816   if ( window && window->isSafeScript(exec) )
01817     return String(toString(exec));
01818   return Undefined();
01819 }
01820 
01821 UString Location::toString(ExecState *exec) const
01822 {
01823   Window* window = Window::retrieveWindow( m_part );
01824   if ( window && window->isSafeScript(exec) )
01825   {
01826     if (!m_part->url().hasPath())
01827       return m_part->url().prettyURL()+"/";
01828     else
01829       return m_part->url().prettyURL();
01830   }
01831   return "";
01832 }
01833 
01834 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01835 {
01836   KJS_CHECK_THIS( Location, thisObj );
01837   Location *location = static_cast<Location *>(thisObj.imp());
01838   KHTMLPart *part = location->part();
01839 
01840   if (!part) return Undefined();
01841 
01842   Window* window = Window::retrieveWindow(part);
01843 
01844   if ( !window->isSafeScript(exec) && id != Location::Replace)
01845       return Undefined();
01846 
01847   switch (id) {
01848   case Location::Assign:
01849   case Location::Replace:
01850     Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(), 
01851             id == Location::Replace);
01852     break;
01853   case Location::Reload:
01854     part->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
01855     break;
01856   case Location::ToString:
01857     return String(location->toString(exec));
01858   }
01859   return Undefined();
01860 }
01861 
01863 
01864 const ClassInfo History::info = { "History", 0, 0, 0 };
01865 /*
01866 @begin HistoryTable 4
01867   length        History::Length         DontDelete|ReadOnly
01868   back          History::Back           DontDelete|Function 0
01869   forward       History::Forward        DontDelete|Function 0
01870   go            History::Go             DontDelete|Function 1
01871 @end
01872 */
01873 IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
01874 
01875 Value History::get(ExecState *exec, const UString &p) const
01876 {
01877   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
01878 }
01879 
01880 Value History::getValueProperty(ExecState *, int token) const
01881 {
01882   switch (token) {
01883   case Length:
01884   {
01885     KParts::BrowserExtension *ext = part->browserExtension();
01886     if ( !ext )
01887       return Number( 0 );
01888 
01889     KParts::BrowserInterface *iface = ext->browserInterface();
01890     if ( !iface )
01891       return Number( 0 );
01892 
01893     QVariant length = iface->property( "historyLength" );
01894 
01895     if ( length.type() != QVariant::UInt )
01896       return Number( 0 );
01897 
01898     return Number( length.toUInt() );
01899   }
01900   default:
01901     kdWarning(6070) << "Unhandled token in History::getValueProperty : " << token << endl;
01902     return Undefined();
01903   }
01904 }
01905 
01906 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
01907 {
01908   KJS_CHECK_THIS( History, thisObj );
01909   History *history = static_cast<History *>(thisObj.imp());
01910 
01911   Value v = args[0];
01912   Number n;
01913   if(!v.isNull())
01914     n = v.toInteger(exec);
01915 
01916   int steps;
01917   switch (id) {
01918   case History::Back:
01919     steps = -1;
01920     break;
01921   case History::Forward:
01922     steps = 1;
01923     break;
01924   case History::Go:
01925     steps = n.intValue();
01926     break;
01927   default:
01928     return Undefined();
01929   }
01930 
01931   // Special case for go(0) from a frame -> reload only the frame
01932   // go(i!=0) from a frame navigates into the history of the frame only,
01933   // in both IE and NS (but not in Mozilla).... we can't easily do that
01934   // in Konqueror...
01935   if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
01936   {
01937     history->part->openURL( history->part->url() ); 
01938   } else
01939   {
01940     // Delay it.
01941     // Testcase: history.back(); alert("hello");
01942     Window* window = Window::retrieveWindow( history->part );
01943     window->delayedGoHistory( steps );
01944   }
01945   return Undefined();
01946 }
01947 
01949 
01950 #ifdef Q_WS_QWS
01951 
01952 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
01953 
01954 bool Konqueror::hasProperty(ExecState *exec, const UString &p) const
01955 {
01956   if ( p.qstring().startsWith( "goHistory" ) ) return false;
01957 
01958   return true;
01959 }
01960 
01961 Value Konqueror::get(ExecState *exec, const UString &p) const
01962 {
01963   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
01964     return Undefined();
01965 
01966   KParts::BrowserExtension *ext = part->browserExtension();
01967   if ( ext ) {
01968     KParts::BrowserInterface *iface = ext->browserInterface();
01969     if ( iface ) {
01970       QVariant prop = iface->property( p.qstring().latin1() );
01971 
01972       if ( prop.isValid() ) {
01973         switch( prop.type() ) {
01974         case QVariant::Int:
01975           return Number( prop.toInt() );
01976         case QVariant::String:
01977           return String( prop.toString() );
01978         default:
01979           break;
01980         }
01981       }
01982     }
01983   }
01984 
01985   return Value /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
01986 }
01987 
01988 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
01989 {
01990   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
01991 
01992   if(!ext)
01993     return Undefined();
01994 
01995   KParts::BrowserInterface *iface = ext->browserInterface();
01996 
01997   if ( !iface )
01998     return Undefined();
01999 
02000   QCString n = m_name.data();
02001   n += "()";
02002   iface->callMethod( n.data(), QVariant() );
02003 
02004   return Undefined();
02005 }
02006 
02007 UString Konqueror::toString(ExecState *) const
02008 {
02009   return UString("[object Konqueror]");
02010 }
02011 
02012 #endif
02013 
02014 
02015 #include "kjs_window.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:34:27 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001