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