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