kjs_window.cpp Source File (khtml Library)

| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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"

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