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