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