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