Reviewed by Maciej
[WebKit-https.git] / WebCore / khtml / ecma / kjs_window.cpp
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2003 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <qstylesheet.h>
23 #include <qtimer.h>
24 #include <qinputdialog.h>
25 #include <qpaintdevicemetrics.h>
26 #include <qapplication.h>
27 #include <kdebug.h>
28 #include <kmessagebox.h>
29 #include <klocale.h>
30 #include <kparts/browserinterface.h>
31 #include <kwin.h>
32 #include <kwinmodule.h>
33 #include <kconfig.h>
34 #include <assert.h>
35 #include <qstyle.h>
36 #include "rendering/render_canvas.h"
37
38 #if APPLE_CHANGES
39 #include "KWQLogging.h"
40 #include "KWQKConfigBase.h"
41 #endif
42 #include <kjs/collector.h>
43 #include "kjs_proxy.h"
44 #include "kjs_window.h"
45 #include "kjs_navigator.h"
46 #include "kjs_html.h"
47 #include "kjs_range.h"
48 #include "kjs_traversal.h"
49 #include "kjs_css.h"
50 #include "kjs_events.h"
51 #include "xmlhttprequest.h"
52 #include "xmlserializer.h"
53
54 #include "khtmlview.h"
55 #include "khtml_part.h"
56 #include "dom/dom_string.h"
57 #include "dom/dom_node.h"
58 #include "editing/htmlediting.h"
59 #include "editing/selection.h"
60 #include "xml/dom2_eventsimpl.h"
61 #include "xml/dom_docimpl.h"
62 #include "xml/dom_position.h"
63 #include "html/html_documentimpl.h"
64
65 using DOM::DocumentImpl;
66 using DOM::DOMString;
67 using DOM::Node;
68 using DOM::Position;
69 using khtml::TypingCommand;
70
71 using namespace KJS;
72
73 namespace KJS {
74
75 ////////////////////// History Object ////////////////////////
76
77   class History : public ObjectImp {
78     friend class HistoryFunc;
79   public:
80     History(ExecState *exec, KHTMLPart *p)
81       : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
82     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
83     Value getValueProperty(ExecState *exec, int token) const;
84     virtual const ClassInfo* classInfo() const { return &info; }
85     static const ClassInfo info;
86     enum { Back, Forward, Go, Length };
87     virtual UString toString(ExecState *exec) const;
88   private:
89     QGuardedPtr<KHTMLPart> part;
90   };
91
92   class FrameArray : public ObjectImp {
93   public:
94     FrameArray(ExecState *exec, KHTMLPart *p)
95       : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
96     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
97     virtual UString toString(ExecState *exec) const;
98   private:
99     QGuardedPtr<KHTMLPart> part;
100   };
101
102 #ifdef Q_WS_QWS
103   class KonquerorFunc : public DOMFunction {
104   public:
105     KonquerorFunc(const Konqueror* k, const char* name)
106       : DOMFunction(), konqueror(k), m_name(name) { }
107     virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
108
109   private:
110     const Konqueror* konqueror;
111     QCString m_name;
112   };
113 #endif
114 }; // namespace KJS
115
116 #include "kjs_window.lut.h"
117
118 ////////////////////// Screen Object ////////////////////////
119
120 // table for screen object
121 /*
122 @begin ScreenTable 7
123   height        Screen::Height          DontEnum|ReadOnly
124   width         Screen::Width           DontEnum|ReadOnly
125   colorDepth    Screen::ColorDepth      DontEnum|ReadOnly
126   pixelDepth    Screen::PixelDepth      DontEnum|ReadOnly
127   availLeft     Screen::AvailLeft       DontEnum|ReadOnly
128   availTop      Screen::AvailTop        DontEnum|ReadOnly
129   availHeight   Screen::AvailHeight     DontEnum|ReadOnly
130   availWidth    Screen::AvailWidth      DontEnum|ReadOnly
131 @end
132 */
133
134 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
135
136 // We set the object prototype so that toString is implemented
137 Screen::Screen(ExecState *exec)
138   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()) {}
139
140 Value Screen::get(ExecState *exec, const Identifier &p) const
141 {
142 #ifdef KJS_VERBOSE
143   kdDebug(6070) << "Screen::get " << p.qstring() << endl;
144 #endif
145   return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
146 }
147
148 Value Screen::getValueProperty(ExecState *exec, int token) const
149 {
150   KWinModule info;
151   QWidget *thisWidget = Window::retrieveActive(exec)->part()->view();
152   QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(thisWidget));
153
154   switch( token ) {
155   case Height:
156     return Number(sg.height());
157   case Width:
158     return Number(sg.width());
159   case ColorDepth:
160   case PixelDepth: {
161     QPaintDeviceMetrics m(QApplication::desktop());
162     return Number(m.depth());
163   }
164   case AvailLeft: {
165     QRect clipped = info.workArea().intersect(sg);
166     return Number(clipped.x()-sg.x());
167   }
168   case AvailTop: {
169     QRect clipped = info.workArea().intersect(sg);
170     return Number(clipped.y()-sg.y());
171   }
172   case AvailHeight: {
173     QRect clipped = info.workArea().intersect(sg);
174     return Number(clipped.height());
175   }
176   case AvailWidth: {
177     QRect clipped = info.workArea().intersect(sg);
178     return Number(clipped.width());
179   }
180   default:
181     kdWarning() << "Screen::getValueProperty unhandled token " << token << endl;
182     return Undefined();
183   }
184 }
185
186 ////////////////////// Window Object ////////////////////////
187
188 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
189
190 /*
191 @begin WindowTable 91
192   closed        Window::Closed          DontDelete|ReadOnly
193   crypto        Window::Crypto          DontDelete|ReadOnly
194   defaultStatus Window::DefaultStatus   DontDelete
195   defaultstatus Window::DefaultStatus   DontDelete
196   status        Window::Status          DontDelete
197   document      Window::Document        DontDelete|ReadOnly
198   Node          Window::Node            DontDelete
199   Event         Window::EventCtor       DontDelete
200   Range         Window::Range           DontDelete
201   NodeFilter    Window::NodeFilter      DontDelete
202   DOMException  Window::DOMException    DontDelete
203   CSSRule       Window::CSSRule         DontDelete
204   frames        Window::Frames          DontDelete|ReadOnly
205   history       Window::_History        DontDelete|ReadOnly
206   event         Window::Event           DontDelete
207   innerHeight   Window::InnerHeight     DontDelete|ReadOnly
208   innerWidth    Window::InnerWidth      DontDelete|ReadOnly
209   length        Window::Length          DontDelete|ReadOnly
210   location      Window::_Location       DontDelete
211   locationbar   Window::Locationbar     DontDelete
212   name          Window::Name            DontDelete
213   navigator     Window::_Navigator      DontDelete|ReadOnly
214   clientInformation     Window::ClientInformation       DontDelete|ReadOnly
215   konqueror     Window::_Konqueror      DontDelete|ReadOnly
216   menubar       Window::Menubar         DontDelete|ReadOnly
217   offscreenBuffering    Window::OffscreenBuffering      DontDelete|ReadOnly
218   opener        Window::Opener          DontDelete|ReadOnly
219   outerHeight   Window::OuterHeight     DontDelete|ReadOnly
220   outerWidth    Window::OuterWidth      DontDelete|ReadOnly
221   pageXOffset   Window::PageXOffset     DontDelete|ReadOnly
222   pageYOffset   Window::PageYOffset     DontDelete|ReadOnly
223   parent        Window::Parent          DontDelete|ReadOnly
224   personalbar   Window::Personalbar     DontDelete|ReadOnly
225   screenX       Window::ScreenX         DontDelete|ReadOnly
226   screenY       Window::ScreenY         DontDelete|ReadOnly
227   screenLeft    Window::ScreenLeft      DontDelete|ReadOnly
228   screenTop     Window::ScreenTop       DontDelete|ReadOnly
229   scrollbars    Window::Scrollbars      DontDelete|ReadOnly
230   statusbar     Window::Statusbar       DontDelete|ReadOnly
231   toolbar       Window::Toolbar         DontDelete|ReadOnly
232   scroll        Window::Scroll          DontDelete|Function 2
233   scrollBy      Window::ScrollBy        DontDelete|Function 2
234   scrollTo      Window::ScrollTo        DontDelete|Function 2
235   scrollX       Window::ScrollX         DontDelete|ReadOnly
236   scrollY       Window::ScrollY         DontDelete|ReadOnly
237   moveBy        Window::MoveBy          DontDelete|Function 2
238   moveTo        Window::MoveTo          DontDelete|Function 2
239   resizeBy      Window::ResizeBy        DontDelete|Function 2
240   resizeTo      Window::ResizeTo        DontDelete|Function 2
241   self          Window::Self            DontDelete|ReadOnly
242   window        Window::_Window         DontDelete|ReadOnly
243   top           Window::Top             DontDelete|ReadOnly
244   screen        Window::_Screen         DontDelete|ReadOnly
245   Image         Window::Image           DontDelete|ReadOnly
246   Option        Window::Option          DontDelete|ReadOnly
247   XMLHttpRequest        Window::XMLHttpRequest  DontDelete|ReadOnly
248   XMLSerializer Window::XMLSerializer   DontDelete|ReadOnly
249   alert         Window::Alert           DontDelete|Function 1
250   confirm       Window::Confirm         DontDelete|Function 1
251   prompt        Window::Prompt          DontDelete|Function 2
252   open          Window::Open            DontDelete|Function 3
253   print         Window::Print           DontDelete|Function 2
254   setTimeout    Window::SetTimeout      DontDelete|Function 2
255   clearTimeout  Window::ClearTimeout    DontDelete|Function 1
256   focus         Window::Focus           DontDelete|Function 0
257   getSelection  Window::GetSelection    DontDelete|Function 0
258   blur          Window::Blur            DontDelete|Function 0
259   close         Window::Close           DontDelete|Function 0
260   setInterval   Window::SetInterval     DontDelete|Function 2
261   clearInterval Window::ClearInterval   DontDelete|Function 1
262   captureEvents Window::CaptureEvents   DontDelete|Function 0
263   releaseEvents Window::ReleaseEvents   DontDelete|Function 0
264 # Warning, when adding a function to this object you need to add a case in Window::get
265   addEventListener      Window::AddEventListener        DontDelete|Function 3
266   removeEventListener   Window::RemoveEventListener     DontDelete|Function 3
267   onabort       Window::Onabort         DontDelete
268   onblur        Window::Onblur          DontDelete
269   onchange      Window::Onchange        DontDelete
270   onclick       Window::Onclick         DontDelete
271   ondblclick    Window::Ondblclick      DontDelete
272   ondragdrop    Window::Ondragdrop      DontDelete
273   onerror       Window::Onerror         DontDelete
274   onfocus       Window::Onfocus         DontDelete
275   onkeydown     Window::Onkeydown       DontDelete
276   onkeypress    Window::Onkeypress      DontDelete
277   onkeyup       Window::Onkeyup         DontDelete
278   onload        Window::Onload          DontDelete
279   onmousedown   Window::Onmousedown     DontDelete
280   onmousemove   Window::Onmousemove     DontDelete
281   onmouseout    Window::Onmouseout      DontDelete
282   onmouseover   Window::Onmouseover     DontDelete
283   onmouseup     Window::Onmouseup       DontDelete
284   onmove        Window::Onmove          DontDelete
285   onreset       Window::Onreset         DontDelete
286   onresize      Window::Onresize        DontDelete
287   onscroll      Window::Onscroll        DontDelete
288   onsearch      Window::Onsearch        DontDelete
289   onselect      Window::Onselect        DontDelete
290   onsubmit      Window::Onsubmit        DontDelete
291   onunload      Window::Onunload        DontDelete
292 @end
293 */
294 IMPLEMENT_PROTOFUNC(WindowFunc)
295
296 Window::Window(KHTMLPart *p)
297   : ObjectImp(/*no proto*/)
298   , m_part(p)
299   , screen(0)
300   , history(0)
301   , frames(0)
302   , loc(0)
303   , m_selection(0)
304   , m_locationbar(0)
305   , m_menubar(0)
306   , m_personalbar(0)
307   , m_scrollbars(0)
308   , m_statusbar(0)
309   , m_toolbar(0)
310   , m_evt(0)
311 {
312   winq = new WindowQObject(this);
313   //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
314 }
315
316 Window::~Window()
317 {
318   kdDebug(6070) << "Window::~Window this=" << this << " part=" << m_part << endl;
319   delete winq;
320 }
321
322 Window *Window::retrieveWindow(KHTMLPart *p)
323 {
324   Object obj = Object::dynamicCast( retrieve( p ) );
325 #ifndef NDEBUG
326   // obj should never be null, except when javascript has been disabled in that part.
327   if ( p && p->jScriptEnabled() )
328   {
329     assert( !obj.isNull() );
330 #ifndef QWS
331     assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
332 #endif
333   }
334 #endif
335   if ( obj.isNull() ) // JS disabled
336     return 0;
337   return static_cast<KJS::Window*>(obj.imp());
338 }
339
340 Window *Window::retrieveActive(ExecState *exec)
341 {
342   ValueImp *imp = exec->dynamicInterpreter()->globalObject().imp();
343   assert( imp );
344 #ifndef QWS
345   assert( dynamic_cast<KJS::Window*>(imp) );
346 #endif
347   return static_cast<KJS::Window*>(imp);
348 }
349
350 Value Window::retrieve(KHTMLPart *p)
351 {
352   assert(p);
353   KJSProxy *proxy = KJSProxy::proxy( p );
354   if (proxy) {
355 #ifdef KJS_VERBOSE
356     kdDebug(6070) << "Window::retrieve part=" << p << " interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
357 #endif
358     return proxy->interpreter()->globalObject(); // the Global object is the "window"
359   } else
360     return Undefined(); // This can happen with JS disabled on the domain of that window
361 }
362
363 Location *Window::location() const
364 {
365   if (!loc)
366     const_cast<Window*>(this)->loc = new Location(m_part);
367   return loc;
368 }
369
370 Selection *Window::selection() const
371 {
372   if (!m_selection)
373     const_cast<Window*>(this)->m_selection = new Selection(m_part);
374   return m_selection;
375 }
376
377 BarInfo *Window::locationbar(ExecState *exec) const
378 {
379   if (!m_locationbar)
380     const_cast<Window*>(this)->m_locationbar = new BarInfo(exec, m_part, BarInfo::Locationbar);
381   return m_locationbar;
382 }
383
384 BarInfo *Window::menubar(ExecState *exec) const
385 {
386   if (!m_menubar)
387     const_cast<Window*>(this)->m_menubar = new BarInfo(exec, m_part, BarInfo::Menubar);
388   return m_menubar;
389 }
390
391 BarInfo *Window::personalbar(ExecState *exec) const
392 {
393   if (!m_personalbar)
394     const_cast<Window*>(this)->m_personalbar = new BarInfo(exec, m_part, BarInfo::Personalbar);
395   return m_personalbar;
396 }
397
398 BarInfo *Window::statusbar(ExecState *exec) const
399 {
400   if (!m_statusbar)
401     const_cast<Window*>(this)->m_statusbar = new BarInfo(exec, m_part, BarInfo::Statusbar);
402   return m_statusbar;
403 }
404
405 BarInfo *Window::toolbar(ExecState *exec) const
406 {
407   if (!m_toolbar)
408     const_cast<Window*>(this)->m_toolbar = new BarInfo(exec, m_part, BarInfo::Toolbar);
409   return m_toolbar;
410 }
411
412 BarInfo *Window::scrollbars(ExecState *exec) const
413 {
414   if (!m_scrollbars)
415     const_cast<Window*>(this)->m_scrollbars = new BarInfo(exec, m_part, BarInfo::Scrollbars);
416   return m_scrollbars;
417 }
418
419 // reference our special objects during garbage collection
420 void Window::mark()
421 {
422   ObjectImp::mark();
423   if (screen && !screen->marked())
424     screen->mark();
425   if (history && !history->marked())
426     history->mark();
427   if (frames && !frames->marked())
428     frames->mark();
429   //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
430   if (loc && !loc->marked())
431     loc->mark();
432   if (m_selection && !m_selection->marked())
433     m_selection->mark();
434   if (m_locationbar && !m_locationbar->marked())
435     m_locationbar->mark();
436   if (m_menubar && !m_menubar->marked())
437     m_menubar->mark();
438   if (m_personalbar && !m_personalbar->marked())
439     m_personalbar->mark();
440   if (m_scrollbars && !m_scrollbars->marked())
441     m_scrollbars->mark();
442   if (m_statusbar && !m_statusbar->marked())
443     m_statusbar->mark();
444   if (m_toolbar && !m_toolbar->marked())
445     m_toolbar->mark();
446 }
447
448 UString Window::toString(ExecState *) const
449 {
450   return "[object Window]";
451 }
452
453 Value Window::get(ExecState *exec, const Identifier &p) const
454 {
455 #ifdef KJS_VERBOSE
456   kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
457 #endif
458   if ( p == "closed" )
459     return Boolean(m_part.isNull());
460
461   // we don't want any properties other than "closed" on a closed window
462   if (m_part.isNull())
463     return Undefined();
464
465   // Look for overrides first
466   ValueImp * val = ObjectImp::getDirect(p);
467   if (val) {
468     //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
469     if (isSafeScript(exec))
470       return Value(val);
471   }
472
473   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
474   if (entry)
475   {
476     //kdDebug(6070) << "token: " << entry->value << endl;
477     switch( entry->value ) {
478     case Crypto:
479       return Undefined(); // ###
480     case DefaultStatus:
481       return String(UString(m_part->jsDefaultStatusBarText()));
482     case Status:
483       return String(UString(m_part->jsStatusBarText()));
484     case Document:
485       if (isSafeScript(exec))
486       {
487         if (m_part->document().isNull()) {
488 #if APPLE_CHANGES
489           KWQ(m_part)->createEmptyDocument();
490 #endif
491           kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
492           m_part->begin();
493           m_part->write("<HTML><BODY>");
494           m_part->end();
495         }
496         Value val = getDOMNode(exec,m_part->document());
497         return val;
498       }
499       else
500         return Undefined();
501     case Node:
502       return getNodeConstructor(exec);
503     case Range:
504       return getRangeConstructor(exec);
505     case NodeFilter:
506       return getNodeFilterConstructor(exec);
507     case DOMException:
508       return getDOMExceptionConstructor(exec);
509     case CSSRule:
510       return getCSSRuleConstructor(exec);
511     case EventCtor:
512       return getEventConstructor(exec);
513     case Frames:
514       return Value(frames ? frames :
515                    (const_cast<Window*>(this)->frames = new FrameArray(exec,m_part)));
516     case _History:
517       return Value(history ? history :
518                    (const_cast<Window*>(this)->history = new History(exec,m_part)));
519
520     case Event:
521       if (m_evt)
522         return getDOMEvent(exec,*m_evt);
523       else {
524 #ifdef KJS_VERBOSE
525         kdWarning(6070) << "window(" << this << "," << m_part->name() << ").event, no event!" << endl;
526 #endif
527         return Undefined();
528       }
529     case InnerHeight:
530       if (!m_part->view())
531         return Undefined();
532       updateLayout();
533       return Number(m_part->view()->visibleHeight());
534     case InnerWidth:
535       if (!m_part->view())
536         return Undefined();
537       updateLayout();
538       return Number(m_part->view()->visibleWidth());
539     case Length:
540       return Number(m_part->frames().count());
541     case _Location:
542       return Value(location());
543     case Name:
544       return String(m_part->name());
545     case _Navigator:
546     case ClientInformation: {
547       // Store the navigator in the object so we get the same one each time.
548       Navigator *n = new Navigator(exec, m_part);
549       const_cast<Window *>(this)->putDirect("navigator", n, DontDelete|ReadOnly);
550       const_cast<Window *>(this)->putDirect("clientInformation", n, DontDelete|ReadOnly);
551       return Value(n);
552     }
553 #ifdef Q_WS_QWS
554     case _Konqueror:
555       return Value(new Konqueror(m_part));
556 #endif
557     case Locationbar:
558       return Value(locationbar(exec));
559     case Menubar:
560       return Value(menubar(exec));
561     case OffscreenBuffering:
562       return Boolean(true);
563     case Opener:
564       if (!m_part->opener())
565         return Null();    // ### a null Window might be better, but == null
566       else                // doesn't work yet
567         return retrieve(m_part->opener());
568     case OuterHeight:
569     case OuterWidth:
570     {
571       if (!m_part->view())
572         return Number(0);
573       KWin::Info inf = KWin::info(m_part->view()->topLevelWidget()->winId());
574       return Number(entry->value == OuterHeight ?
575                     inf.geometry.height() : inf.geometry.width());
576     }
577     case PageXOffset:
578       if (!m_part->view())
579         return Undefined();
580       updateLayout();
581       return Number(m_part->view()->contentsX());
582     case PageYOffset:
583       if (!m_part->view())
584         return Undefined();
585       updateLayout();
586       return Number(m_part->view()->contentsY());
587     case Parent:
588       return Value(retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part));
589     case Personalbar:
590       return Value(personalbar(exec));
591     case ScreenLeft:
592     case ScreenX: {
593       if (!m_part->view())
594         return Undefined();
595       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
596       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
597     }
598     case ScreenTop:
599     case ScreenY: {
600       if (!m_part->view())
601         return Undefined();
602       QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
603       return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
604     }
605     case ScrollX: {
606       if (!m_part->view())
607         return Undefined();
608       updateLayout();
609       return Number(m_part->view()->contentsX());
610     }
611     case ScrollY: {
612       if (!m_part->view())
613         return Undefined();
614       updateLayout();
615       return Number(m_part->view()->contentsY());
616     }
617     case Scrollbars:
618       return Value(scrollbars(exec));
619     case Statusbar:
620       return Value(statusbar(exec));
621     case Toolbar:
622       return Value(toolbar(exec));
623     case Self:
624     case _Window:
625       return Value(retrieve(m_part));
626     case Top: {
627       KHTMLPart *p = m_part;
628       while (p->parentPart())
629         p = p->parentPart();
630       return Value(retrieve(p));
631     }
632     case _Screen:
633       return Value(screen ? screen :
634                    (const_cast<Window*>(this)->screen = new Screen(exec)));
635     case Image:
636       return Value(new ImageConstructorImp(exec, m_part->document()));
637     case Option:
638       return Value(new OptionConstructorImp(exec, m_part->document()));
639     case XMLHttpRequest:
640       return Value(new XMLHttpRequestConstructorImp(exec, m_part->document()));
641     case XMLSerializer:
642       return Value(new XMLSerializerConstructorImp(exec));
643     case Alert:
644     case Confirm:
645     case Prompt:
646     case Open:
647 #if APPLE_CHANGES
648     case Print:
649 #endif
650     case Focus:
651     case Blur:
652     case Close:
653     case Scroll: // compatibility
654     case ScrollBy:
655     case ScrollTo:
656     case MoveBy:
657     case MoveTo:
658     case ResizeBy:
659     case ResizeTo:
660         return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
661     case CaptureEvents:
662     case ReleaseEvents:
663     case AddEventListener:
664     case RemoveEventListener:
665     case SetTimeout:
666     case ClearTimeout:
667     case SetInterval:
668     case ClearInterval:
669     case GetSelection:
670       if (isSafeScript(exec))
671         return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
672       else
673         return Undefined();
674     case Onabort:
675       if (isSafeScript(exec))
676         return getListener(exec,DOM::EventImpl::ABORT_EVENT);
677       else
678         return Undefined();
679     case Onblur:
680       if (isSafeScript(exec))
681         return getListener(exec,DOM::EventImpl::BLUR_EVENT);
682       else
683         return Undefined();
684     case Onchange:
685       if (isSafeScript(exec))
686         return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
687       else
688         return Undefined();
689     case Onclick:
690       if (isSafeScript(exec))
691         return getListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT);
692       else
693         return Undefined();
694     case Ondblclick:
695       if (isSafeScript(exec))
696         return getListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT);
697       else
698         return Undefined();
699     case Ondragdrop:
700       if (isSafeScript(exec))
701         return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
702       else
703         return Undefined();
704     case Onerror:
705       if (isSafeScript(exec))
706         return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
707       else
708         return Undefined();
709     case Onfocus:
710       if (isSafeScript(exec))
711         return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
712       else
713         return Undefined();
714     case Onkeydown:
715       if (isSafeScript(exec))
716         return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
717       else
718         return Undefined();
719     case Onkeypress:
720       if (isSafeScript(exec))
721         return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
722       else
723         return Undefined();
724     case Onkeyup:
725       if (isSafeScript(exec))
726         return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
727       else
728         return Undefined();
729     case Onload:
730       if (isSafeScript(exec))
731         return getListener(exec,DOM::EventImpl::LOAD_EVENT);
732       else
733         return Undefined();
734     case Onmousedown:
735       if (isSafeScript(exec))
736         return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
737       else
738         return Undefined();
739     case Onmousemove:
740       if (isSafeScript(exec))
741         return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
742       else
743         return Undefined();
744     case Onmouseout:
745       if (isSafeScript(exec))
746         return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
747       else
748         return Undefined();
749     case Onmouseover:
750       if (isSafeScript(exec))
751         return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
752       else
753         return Undefined();
754     case Onmouseup:
755       if (isSafeScript(exec))
756         return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
757       else
758         return Undefined();
759     case Onmove:
760       if (isSafeScript(exec))
761         return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
762       else
763         return Undefined();
764     case Onreset:
765       if (isSafeScript(exec))
766         return getListener(exec,DOM::EventImpl::RESET_EVENT);
767       else
768         return Undefined();
769     case Onresize:
770       if (isSafeScript(exec))
771         return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
772       else
773         return Undefined();
774     case Onscroll:
775         if (isSafeScript(exec))
776             return getListener(exec,DOM::EventImpl::SCROLL_EVENT);
777         else
778             return Undefined();
779 #if APPLE_CHANGES
780     case Onsearch:
781         if (isSafeScript(exec))
782             return getListener(exec,DOM::EventImpl::SEARCH_EVENT);
783         else
784             return Undefined();
785 #endif
786     case Onselect:
787       if (isSafeScript(exec))
788         return getListener(exec,DOM::EventImpl::SELECT_EVENT);
789       else
790         return Undefined();
791     case Onsubmit:
792       if (isSafeScript(exec))
793         return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
794       else
795         return Undefined();
796     case Onunload:
797       if (isSafeScript(exec))
798         return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
799       else
800         return Undefined();
801     }
802   }
803
804   KHTMLPart *kp = m_part->findFrame( p.qstring() );
805   if (kp)
806     return Value(retrieve(kp));
807
808   // allow window[1] or parent[1] etc. (#56983)
809   bool ok;
810   unsigned int i = p.toArrayIndex(&ok);
811   if (ok) {
812     QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
813     unsigned int len = frames.count();
814     if (i < len) {
815       KParts::ReadOnlyPart* frame = frames.at(i);
816       if (frame && frame->inherits("KHTMLPart")) {
817         KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
818         return Window::retrieve(khtml);
819       }
820     }
821   }
822
823   // allow shortcuts like 'Image1' instead of document.images.Image1
824   if (isSafeScript(exec) &&
825       m_part->document().isHTMLDocument()) { // might be XML
826     DOM::HTMLCollection coll = m_part->htmlDocument().all();
827     DOM::HTMLElement element = coll.namedItem(p.string());
828     if (!element.isNull()) {
829       return getDOMNode(exec,element);
830     }
831   }
832
833   // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
834   // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
835 #ifdef KJS_VERBOSE
836   kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
837 #endif
838   return Undefined();
839 }
840
841 bool Window::hasProperty(ExecState *exec, const Identifier &p) const
842 {
843   // matches logic in get function above, but no need to handle numeric values (frame indices)
844
845   if (m_part.isNull())
846     return p == "closed";
847
848   if (getDirect(p))
849     return true;
850
851   if (Lookup::findEntry(&WindowTable, p))
852     return true;
853
854   if (m_part->findFrame(p.qstring()))
855     return true;
856
857   if (!m_part->htmlDocument().all().namedItem(p.string()).isNull())
858     return true;
859
860   return false;
861 }
862
863 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
864 {
865   // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
866   // If yes, save time and jump directly to ObjectImp.
867   if ( (attr != None && attr != DontDelete)
868        // Same thing if we have a local override (e.g. "var location")
869        || ( ObjectImp::getDirect(propertyName) && isSafeScript(exec)) )
870   {
871     ObjectImp::put( exec, propertyName, value, attr );
872     return;
873   }
874
875   const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
876   if (entry)
877   {
878 #ifdef KJS_VERBOSE
879     kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
880 #endif
881     switch( entry->value ) {
882     case Status: {
883       String s = value.toString(exec);
884       m_part->setJSStatusBarText(s.value().qstring());
885       return;
886     }
887     case DefaultStatus: {
888       String s = value.toString(exec);
889       m_part->setJSDefaultStatusBarText(s.value().qstring());
890       return;
891     }
892     case _Location: {
893       KHTMLPart* p = Window::retrieveActive(exec)->m_part;
894       if (p) {
895         QString dstUrl = p->htmlDocument().completeURL(value.toString(exec).string()).string();
896         if (dstUrl.find("javascript:", 0, false) || isSafeScript(exec))
897         {
898           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
899 #if APPLE_CHANGES
900           // We want a new history item if this JS was called via a user gesture
901           m_part->scheduleLocationChange(dstUrl, !userGesture, userGesture);
902 #else
903           m_part->scheduleLocationChange(dstUrl, false /*don't lock history*/, userGesture);
904 #endif
905         }
906       }
907       return;
908     }
909     case Onabort:
910       if (isSafeScript(exec))
911         setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
912       return;
913     case Onblur:
914       if (isSafeScript(exec))
915         setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
916       return;
917     case Onchange:
918       if (isSafeScript(exec))
919         setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
920       return;
921     case Onclick:
922       if (isSafeScript(exec))
923         setListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT,value);
924       return;
925     case Ondblclick:
926       if (isSafeScript(exec))
927         setListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT,value);
928       return;
929     case Ondragdrop:
930       if (isSafeScript(exec))
931         setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
932       return;
933     case Onerror:
934       if (isSafeScript(exec))
935         setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
936       return;
937     case Onfocus:
938       if (isSafeScript(exec))
939         setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
940       return;
941     case Onkeydown:
942       if (isSafeScript(exec))
943         setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
944       return;
945     case Onkeypress:
946       if (isSafeScript(exec))
947         setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
948       return;
949     case Onkeyup:
950       if (isSafeScript(exec))
951         setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
952       return;
953     case Onload:
954       if (isSafeScript(exec))
955         setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
956       return;
957     case Onmousedown:
958       if (isSafeScript(exec))
959         setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
960       return;
961     case Onmousemove:
962       if (isSafeScript(exec))
963         setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
964       return;
965     case Onmouseout:
966       if (isSafeScript(exec))
967         setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
968       return;
969     case Onmouseover:
970       if (isSafeScript(exec))
971         setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
972       return;
973     case Onmouseup:
974       if (isSafeScript(exec))
975         setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
976       return;
977     case Onmove:
978       if (isSafeScript(exec))
979         setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
980       return;
981     case Onreset:
982       if (isSafeScript(exec))
983         setListener(exec,DOM::EventImpl::RESET_EVENT,value);
984       return;
985     case Onresize:
986       if (isSafeScript(exec))
987         setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
988       return;
989     case Onscroll:
990       if (isSafeScript(exec))
991         setListener(exec,DOM::EventImpl::SCROLL_EVENT,value);
992       return;
993 #if APPLE_CHANGES
994     case Onsearch:
995         if (isSafeScript(exec))
996             setListener(exec,DOM::EventImpl::SEARCH_EVENT,value);
997         return;
998 #endif
999     case Onselect:
1000       if (isSafeScript(exec))
1001         setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
1002       return;
1003     case Onsubmit:
1004       if (isSafeScript(exec))
1005         setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
1006       return;
1007     case Onunload:
1008       if (isSafeScript(exec))
1009         setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
1010       return;
1011     case Name:
1012       if (isSafeScript(exec))
1013 #if APPLE_CHANGES
1014         m_part->setName( value.toString(exec).qstring() );
1015 #else
1016         m_part->setName( value.toString(exec).qstring().local8Bit().data() );
1017 #endif
1018       return;
1019     default:
1020       break;
1021     }
1022   }
1023   if (isSafeScript(exec)) {
1024     //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
1025     ObjectImp::put(exec, propertyName, value, attr);
1026   }
1027 }
1028
1029 bool Window::toBoolean(ExecState *) const
1030 {
1031   return !m_part.isNull();
1032 }
1033
1034 int Window::installTimeout(const UString &handler, int t, bool singleShot)
1035 {
1036   return winq->installTimeout(handler, t, singleShot);
1037 }
1038
1039 int Window::installTimeout(const Value &function, List &args, int t, bool singleShot)
1040 {
1041   return winq->installTimeout(function, args, t, singleShot);
1042 }
1043
1044 void Window::clearTimeout(int timerId)
1045 {
1046   winq->clearTimeout(timerId);
1047 }
1048
1049 #if APPLE_CHANGES
1050 bool Window::hasTimeouts()
1051 {
1052     return winq->hasTimeouts();
1053 }
1054
1055 QMap<int, ScheduledAction*> *Window::pauseTimeouts(const void *key)
1056 {
1057     return winq->pauseTimeouts(key);
1058 }
1059
1060 void Window::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
1061 {
1062     return winq->resumeTimeouts(sa, key);
1063 }
1064 #endif
1065
1066 void Window::scheduleClose()
1067 {
1068   kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
1069   Q_ASSERT(winq);
1070 #if APPLE_CHANGES
1071   KWQ(m_part)->scheduleClose();
1072 #else
1073   QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
1074 #endif
1075 }
1076
1077 static bool shouldLoadAsEmptyDocument(const KURL &url)
1078 {
1079   return url.protocol().lower() == "about" || url.isEmpty();
1080 }
1081
1082 bool Window::isSafeScript(ExecState *exec) const
1083 {
1084   if (m_part.isNull()) { // part deleted ? can't grant access
1085     kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
1086     return false;
1087   }
1088   KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
1089   if (!activePart) {
1090     kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
1091     return false;
1092   }
1093   if ( activePart == m_part ) // Not calling from another frame, no problem.
1094     return true;
1095
1096   // JS may be attempting to access the "window" object, which should be valid,
1097   // even if the document hasn't been constructed yet.  If the document doesn't
1098   // exist yet allow JS to access the window object.
1099   if (!m_part->xmlDocImpl())
1100       return true;
1101
1102   DOM::DocumentImpl* thisDocument = m_part->xmlDocImpl();
1103   DOM::DocumentImpl* actDocument = activePart->xmlDocImpl();
1104
1105   if (!actDocument) {
1106     kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
1107     return false;
1108   }
1109
1110   DOM::DOMString actDomain = actDocument->domain();
1111   
1112   // Always allow local pages to execute any JS.
1113   if (actDomain.isNull())
1114     return true;
1115   
1116   DOM::DOMString thisDomain = thisDocument->domain();
1117
1118   // if this document is being initially loaded as empty by its parent
1119   // or opener, allow access from any document in the same domain as
1120   // the parent or opener.
1121   if (shouldLoadAsEmptyDocument(m_part->url())) {
1122     KHTMLPart *ancestorPart = m_part->opener() ? m_part->opener() : m_part->parentPart();
1123     while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
1124       ancestorPart = ancestorPart->parentPart();
1125     }
1126     
1127     if (ancestorPart)
1128       thisDomain = ancestorPart->xmlDocImpl()->domain();
1129   }
1130
1131   //kdDebug(6070) << "current domain:" << actDomain.string() << ", frame domain:" << thisDomain.string() << endl;
1132   if ( actDomain == thisDomain )
1133     return true;
1134
1135 #if APPLE_CHANGES
1136   if (Interpreter::shouldPrintExceptions()) {
1137       printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1138              thisDocument->URL().latin1(), actDocument->URL().latin1());
1139       QString message;
1140       message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n", 
1141                       thisDocument->URL().latin1(), actDocument->URL().latin1());
1142       KWQ(m_part)->addMessageToConsole(message, 1, QString()); //fixme: provide a real line number and sourceurl
1143   }
1144 #endif
1145   
1146   kdWarning(6070) << "Javascript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
1147   return false;
1148 }
1149
1150 void Window::setListener(ExecState *exec, int eventId, Value func)
1151 {
1152   if (!isSafeScript(exec))
1153     return;
1154   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1155   if (!doc)
1156     return;
1157
1158   doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
1159 }
1160
1161 Value Window::getListener(ExecState *exec, int eventId) const
1162 {
1163   if (!isSafeScript(exec))
1164     return Undefined();
1165   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1166   if (!doc)
1167     return Undefined();
1168
1169   DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
1170   if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
1171     return static_cast<JSEventListener*>(listener)->listenerObj();
1172   else
1173     return Null();
1174 }
1175
1176
1177 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
1178 {
1179   // This function is so hot that it's worth coding it directly with imps.
1180   if (val.type() != ObjectType)
1181     return 0;
1182   ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
1183
1184   JSEventListener *existingListener = jsEventListeners[listenerObject];
1185   if (existingListener)
1186     return existingListener;
1187
1188   // Note that the JSEventListener constructor adds it to our jsEventListeners list
1189   return new JSEventListener(Object(listenerObject), Object(this), html);
1190 }
1191
1192 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, bool html, int lineNumber)
1193 {
1194   return new JSLazyEventListener(code, Object(this), html, lineNumber);
1195 }
1196
1197 void Window::clear( ExecState *exec )
1198 {
1199   KJS::Interpreter::lock();
1200   kdDebug(6070) << "Window::clear " << this << endl;
1201   delete winq;
1202   winq = new WindowQObject(this);;
1203   // Get rid of everything, those user vars could hold references to DOM nodes
1204   deleteAllProperties( exec );
1205   // Really delete those properties, so that the DOM nodes get deref'ed
1206   KJS::Collector::collect();
1207   // Now recreate a working global object for the next URL that will use us
1208   KJS::Interpreter *interpreter = KJSProxy::proxy( m_part )->interpreter();
1209   interpreter->initGlobalObject();
1210   KJS::Interpreter::unlock();
1211 }
1212
1213 void Window::setCurrentEvent( DOM::Event *evt )
1214 {
1215   m_evt = evt;
1216   //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
1217 }
1218
1219 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1220 {
1221   if (!thisObj.inherits(&Window::info)) {
1222     Object err = Error::create(exec,TypeError);
1223     exec->setException(err);
1224     return err;
1225   }
1226   Window *window = static_cast<Window *>(thisObj.imp());
1227   QString str, str2;
1228
1229   KHTMLPart *part = window->m_part;
1230   if (!part)
1231     return Undefined();
1232
1233   KHTMLView *widget = part->view();
1234   Value v = args[0];
1235   UString s = v.toString(exec);
1236   str = s.qstring();
1237
1238   switch (id) {
1239   case Window::Alert:
1240     if (part && part->xmlDocImpl())
1241       part->xmlDocImpl()->updateRendering();
1242 #if APPLE_CHANGES
1243     KWQ(part)->runJavaScriptAlert(str);
1244 #else
1245     KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
1246 #endif
1247     return Undefined();
1248   case Window::Confirm:
1249     if (part && part->xmlDocImpl())
1250       part->xmlDocImpl()->updateRendering();
1251 #if APPLE_CHANGES
1252     return Boolean(KWQ(part)->runJavaScriptConfirm(str));
1253 #else
1254     return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
1255                                                 i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
1256 #endif
1257   case Window::Prompt:
1258     if (part && part->xmlDocImpl())
1259       part->xmlDocImpl()->updateRendering();
1260     bool ok;
1261 #if APPLE_CHANGES
1262     ok = KWQ(part)->runJavaScriptPrompt(str, args.size() >= 2 ? args[1].toString(exec).qstring() : QString::null, str2);
1263 #else
1264     if (args.size() >= 2)
1265       str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1266                                    QStyleSheet::convertFromPlainText(str),
1267                                    QLineEdit::Normal,
1268                                    args[1].toString(exec).qstring(), &ok);
1269     else
1270       str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1271                                    QStyleSheet::convertFromPlainText(str),
1272                                    QLineEdit::Normal,
1273                                    QString::null, &ok);
1274 #endif
1275     if ( ok )
1276         return String(str2);
1277     else
1278         return Null();
1279   case Window::Open:
1280   {
1281     KConfig *config = new KConfig("konquerorrc");
1282     config->setGroup("Java/JavaScript Settings");
1283 #if !APPLE_CHANGES
1284     int policy = config->readUnsignedNumEntry( "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1285 #else    
1286     int policy = config->readUnsignedNumEntry( part->settings(), "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1287 #endif
1288     delete config;
1289     if ( policy == 1 ) {
1290 #if !APPLE_CHANGES
1291       if ( KMessageBox::questionYesNo(widget,
1292                                       i18n( "This site is trying to open up a new browser "
1293                                             "window using Javascript.\n"
1294                                             "Do you want to allow this?" ),
1295                                       i18n( "Confirmation: Javascript Popup" ) ) == KMessageBox::Yes )
1296 #endif
1297         policy = 0;
1298     } else if ( policy == 3 ) // smart
1299     {
1300       // window.open disabled unless from a key/mouse event
1301       if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture())
1302 #if !APPLE_CHANGES
1303         policy = 0;
1304 #else
1305       {
1306         policy = 0;
1307         LOG(PopupBlocking, "Allowed JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1308       } else {
1309         LOG(PopupBlocking, "Blocked JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1310       }
1311 #endif
1312     }
1313
1314     QString frameName = !args[1].isNull() && args[1].type() != UndefinedType ?
1315                         args[1].toString(exec).qstring()
1316                         : QString("_blank");
1317
1318     if ( policy != 0 && !(part->findFrame(frameName) || frameName == "_top" || frameName == "_parent" || frameName == "_self")) {
1319       return Undefined();
1320     } else {
1321       if (v.type() == UndefinedType)
1322         str = QString();
1323
1324       KParts::WindowArgs winargs;
1325
1326       // scan feature argument
1327       v = args[2];
1328       QString features;
1329       if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
1330         features = v.toString(exec).qstring();
1331         // specifying window params means false defaults
1332         winargs.menuBarVisible = false;
1333         winargs.toolBarsVisible = false;
1334         winargs.statusBarVisible = false;
1335 #if APPLE_CHANGES
1336         winargs.scrollbarsVisible = true;
1337 #endif
1338         QStringList flist = QStringList::split(',', features);
1339         QStringList::ConstIterator it = flist.begin();
1340         while (it != flist.end()) {
1341           QString s = *it++;
1342           QString key, val;
1343           int pos = s.find('=');
1344           if (pos >= 0) {
1345             key = s.left(pos).stripWhiteSpace().lower();
1346             val = s.mid(pos + 1).stripWhiteSpace().lower();
1347             int spacePos = val.find(' ');
1348             if (spacePos != -1) {
1349               val = val.left(spacePos);
1350             }
1351
1352             int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
1353
1354             QRect screen = QApplication::desktop()->screenGeometry(scnum);
1355             if (key == "left" || key == "screenx") {
1356               bool ok;
1357               double d = val.toDouble(&ok);
1358               if (d != 0 || ok) {
1359                 d += screen.x();
1360                 if (d < screen.x() || d > screen.right())
1361                   d = screen.x(); // only safe choice until size is determined
1362                 winargs.x = (int)d;
1363 #if APPLE_CHANGES
1364                 winargs.xSet = true;
1365 #endif
1366               }
1367             } else if (key == "top" || key == "screeny") {
1368               bool ok;
1369               double d = val.toDouble(&ok);
1370               if (d != 0 || ok) {
1371                 d += screen.y();
1372                 if (d < screen.y() || d > screen.bottom())
1373                   d = screen.y(); // only safe choice until size is determined
1374                 winargs.y = (int)d;
1375 #if APPLE_CHANGES
1376                 winargs.ySet = true;
1377 #endif
1378               }
1379             } else if (key == "height") {
1380               bool ok;
1381               double d = val.toDouble(&ok);
1382               if (d != 0 || ok) {
1383 #if !APPLE_CHANGES
1384                 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1385 #endif
1386                 if (d > screen.height())  // should actually check workspace
1387                   d = screen.height();
1388                 if (d < 100)
1389                   d = 100;
1390                 winargs.height = (int)d;
1391 #if APPLE_CHANGES
1392                 winargs.heightSet = true;
1393 #endif
1394               }
1395             } else if (key == "width") {
1396               bool ok;
1397               double d = val.toDouble(&ok);
1398               if (d != 0 || ok) {
1399 #if !APPLE_CHANGES
1400                 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1401 #endif
1402                 if (d > screen.width())    // should actually check workspace
1403                   d = screen.width();
1404                 if (d < 100)
1405                   d = 100;
1406                 winargs.width = (int)d;
1407 #if APPLE_CHANGES
1408                 winargs.widthSet = true;
1409 #endif
1410               }
1411             } else {
1412               goto boolargs;
1413             }
1414             continue;
1415           } else {
1416             // leaving away the value gives true
1417             key = s.stripWhiteSpace().lower();
1418             val = "1";
1419           }
1420         boolargs:
1421           if (key == "menubar")
1422             winargs.menuBarVisible = (val == "1" || val == "yes");
1423           else if (key == "toolbar")
1424             winargs.toolBarsVisible = (val == "1" || val == "yes");
1425           else if (key == "location")  // ### missing in WindowArgs
1426             winargs.toolBarsVisible = (val == "1" || val == "yes");
1427           else if (key == "status" || key == "statusbar")
1428             winargs.statusBarVisible = (val == "1" || val == "yes");
1429           else if (key == "resizable")
1430             winargs.resizable = (val == "1" || val == "yes");
1431           else if (key == "fullscreen")
1432             winargs.fullscreen = (val == "1" || val == "yes");
1433 #if APPLE_CHANGES
1434           else if (key == "scrollbars")
1435             winargs.scrollbarsVisible = !(val == "0" || val == "no");
1436 #endif
1437         }
1438       }
1439
1440       // prepare arguments
1441       KURL url;
1442       if (!str.isEmpty())
1443       {
1444         KHTMLPart* p = Window::retrieveActive(exec)->m_part;
1445         if ( p )
1446           url = p->htmlDocument().completeURL(str).string();
1447       }
1448
1449       KParts::URLArgs uargs;
1450       uargs.frameName = frameName;
1451       if ( uargs.frameName == "_top" )
1452       {
1453           // FIXME: referrer?
1454           while ( part->parentPart() )
1455               part = part->parentPart();
1456           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1457           part->scheduleLocationChange(url.url(), false/*don't lock history*/, userGesture);
1458           return Window::retrieve(part);
1459       }
1460       if ( uargs.frameName == "_parent" )
1461       {
1462           // FIXME: referrer?
1463           if ( part->parentPart() )
1464               part = part->parentPart();
1465           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1466           part->scheduleLocationChange(url.url(), false/*don't lock history*/, userGesture);
1467           return Window::retrieve(part);
1468       }
1469       uargs.serviceType = "text/html";
1470
1471       // request window (new or existing if framename is set)
1472       KParts::ReadOnlyPart *newPart = 0L;
1473       emit part->browserExtension()->createNewWindow("", uargs,winargs,newPart);
1474       if (newPart && newPart->inherits("KHTMLPart")) {
1475         KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
1476         //qDebug("opener set to %p (this Window's part) in new Window %p  (this Window=%p)",part,win,window);
1477         khtmlpart->setOpener(part);
1478         khtmlpart->setOpenedByJS(true);
1479         
1480         if (khtmlpart->document().isNull()) {
1481             DocumentImpl *oldDoc = part->xmlDocImpl();
1482             if (oldDoc && oldDoc->baseURL() != 0)
1483                 khtmlpart->begin(oldDoc->baseURL());
1484             else
1485                 khtmlpart->begin();
1486             
1487             khtmlpart->write("<HTML><BODY>");
1488             khtmlpart->end();
1489
1490             if (oldDoc) {
1491               kdDebug(6070) << "Setting domain to " << oldDoc->domain().string() << endl;
1492               khtmlpart->xmlDocImpl()->setDomain( oldDoc->domain(), true );
1493               khtmlpart->xmlDocImpl()->setBaseURL( oldDoc->baseURL() );
1494             }
1495         }
1496 #if APPLE_CHANGES
1497         if (!url.isEmpty()) {
1498           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1499           // FIXME: Need to pass referrer here.
1500           khtmlpart->scheduleLocationChange(url.url(), false, userGesture);
1501         }
1502 #else
1503         uargs.serviceType = QString::null;
1504         if (uargs.frameName == "_blank")
1505           uargs.frameName = QString::null;
1506         if (!url.isEmpty())
1507           // FIXME: need to pass referrer here
1508           emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
1509 #endif
1510         return Window::retrieve(khtmlpart); // global object
1511       } else
1512         return Undefined();
1513     }
1514   }
1515 #if APPLE_CHANGES
1516   case Window::Print:
1517     part->print();
1518     return Undefined();
1519 #endif
1520   case Window::ScrollBy:
1521     window->updateLayout();
1522     if(args.size() >= 2 && widget)
1523       widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
1524     return Undefined();
1525   case Window::Scroll:
1526   case Window::ScrollTo:
1527     window->updateLayout();
1528     if(args.size() >= 2 && widget)
1529       widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
1530     return Undefined();
1531   case Window::MoveBy:
1532     if(args.size() >= 2 && widget)
1533     {
1534       QWidget * tl = widget->topLevelWidget();
1535           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1536       QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
1537       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1538       if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
1539            dest.x()+tl->width() <= sg.width()+sg.x() &&
1540            dest.y()+tl->height() <= sg.height()+sg.y() )
1541         tl->move( dest );
1542     }
1543     return Undefined();
1544   case Window::MoveTo:
1545     if(args.size() >= 2 && widget)
1546     {
1547       QWidget * tl = widget->topLevelWidget();
1548           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1549       QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
1550       // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1551       if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
1552            dest.x()+tl->width() <= sg.width()+sg.x() &&
1553            dest.y()+tl->height() <= sg.height()+sg.y() )
1554         tl->move( dest );
1555     }
1556     return Undefined();
1557   case Window::ResizeBy:
1558     if(args.size() >= 2 && widget)
1559     {
1560       QWidget * tl = widget->topLevelWidget();
1561       QSize dest = tl->size() + QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1562           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1563       // Security check: within desktop limits and bigger than 100x100 (per spec)
1564       if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1565            tl->y()+dest.height() <= sg.y()+sg.height() &&
1566            dest.width() >= 100 && dest.height() >= 100 )
1567       {
1568         // Take into account the window frame
1569         int deltaWidth = tl->frameGeometry().width() - tl->width();
1570         int deltaHeight = tl->frameGeometry().height() - tl->height();
1571         tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1572       }
1573     }
1574     return Undefined();
1575   case Window::ResizeTo:
1576     if(args.size() >= 2 && widget)
1577     {
1578       QWidget * tl = widget->topLevelWidget();
1579       QSize dest = QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1580           QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1581       // Security check: within desktop limits and bigger than 100x100 (per spec)
1582       if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1583            tl->y()+dest.height() <= sg.y()+sg.height() &&
1584            dest.width() >= 100 && dest.height() >= 100 )
1585       {
1586         // Take into account the window frame
1587         int deltaWidth = tl->frameGeometry().width() - tl->width();
1588         int deltaHeight = tl->frameGeometry().height() - tl->height();
1589         tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1590       }
1591     }
1592     return Undefined();
1593   case Window::SetTimeout:
1594     if (!window->isSafeScript(exec))
1595         return Undefined();
1596     if (args.size() >= 2 && v.isA(StringType)) {
1597       int i = args[1].toInt32(exec);
1598       int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
1599       return Number(r);
1600     }
1601     else if (args.size() >= 2 && v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
1602       Value func = args[0];
1603       int i = args[1].toInt32(exec);
1604
1605       // All arguments after the second should go to the function
1606       // FIXME: could be more efficient
1607       List funcArgs = args.copyTail().copyTail();
1608
1609       int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, true /*single shot*/);
1610       return Number(r);
1611     }
1612     else
1613       return Undefined();
1614   case Window::SetInterval:
1615     if (!window->isSafeScript(exec))
1616         return Undefined();
1617     if (args.size() >= 2 && v.isA(StringType)) {
1618       int i = args[1].toInt32(exec);
1619       int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
1620       return Number(r);
1621     }
1622     else if (args.size() >= 2 && !Object::dynamicCast(v).isNull() &&
1623              Object::dynamicCast(v).implementsCall()) {
1624       Value func = args[0];
1625       int i = args[1].toInt32(exec);
1626
1627       // All arguments after the second should go to the function
1628       // FIXME: could be more efficient
1629       List funcArgs = args.copyTail().copyTail();
1630
1631       int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, false);
1632       return Number(r);
1633     }
1634     else
1635       return Undefined();
1636   case Window::ClearTimeout:
1637   case Window::ClearInterval:
1638     if (!window->isSafeScript(exec))
1639         return Undefined();
1640     (const_cast<Window*>(window))->clearTimeout(v.toInt32(exec));
1641     return Undefined();
1642   case Window::Focus:
1643     if (widget)
1644       widget->setActiveWindow();
1645     return Undefined();
1646   case Window::GetSelection:
1647     if (!window->isSafeScript(exec))
1648         return Undefined();
1649     return Value(window->selection());
1650   case Window::Blur:
1651 #if APPLE_CHANGES
1652     KWQ(part)->unfocusWindow();
1653 #else
1654     // TODO
1655 #endif
1656     return Undefined();
1657   case Window::Close:
1658     /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
1659        The close method closes only windows opened by JavaScript using the open method.
1660        If you attempt to close any other window, a confirm is generated, which
1661        lets the user choose whether the window closes.
1662        This is a security feature to prevent "mail bombs" containing self.close().
1663        However, if the window has only one document (the current one) in its
1664        session history, the close is allowed without any confirm. This is a
1665        special case for one-off windows that need to open other windows and
1666        then dispose of themselves.
1667     */
1668     if (!part->openedByJS())
1669     {
1670       // To conform to the SPEC, we only ask if the window
1671       // has more than one entry in the history (NS does that too).
1672       History history(exec,part);
1673       if ( history.get( exec, lengthPropertyName ).toInt32(exec) <= 1
1674 #if APPLE_CHANGES
1675            // FIXME: How are we going to handle this?
1676 #else
1677            || KMessageBox::questionYesNo( window->part()->view(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes
1678 #endif
1679            )
1680         (const_cast<Window*>(window))->scheduleClose();
1681     }
1682     else
1683     {
1684       (const_cast<Window*>(window))->scheduleClose();
1685     }
1686     return Undefined();
1687   case Window::CaptureEvents:
1688   case Window::ReleaseEvents:
1689         // If anyone implements these, they need the safescript security check.
1690         if (!window->isSafeScript(exec))
1691             return Undefined();
1692
1693     // Do nothing for now. These are NS-specific legacy calls.
1694     break;
1695   case Window::AddEventListener: {
1696         if (!window->isSafeScript(exec))
1697             return Undefined();
1698         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1699         if (listener) {
1700             DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1701             if (docimpl)
1702                 docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1703         }
1704         return Undefined();
1705     }
1706   case Window::RemoveEventListener: {
1707         if (!window->isSafeScript(exec))
1708             return Undefined();
1709         JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1710         if (listener) {
1711             DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1712             if (docimpl)
1713                 docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1714         }
1715         return Undefined();
1716     }
1717
1718   }
1719   return Undefined();
1720 }
1721
1722 void Window::updateLayout() const
1723 {
1724   DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(m_part->document().handle());
1725   if (docimpl) {
1726     docimpl->updateLayoutIgnorePendingStylesheets();
1727   }
1728 }
1729
1730
1731 ////////////////////// ScheduledAction ////////////////////////
1732
1733 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
1734 {
1735   //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
1736   func = _func;
1737   args = _args;
1738   isFunction = true;
1739   singleShot = _singleShot;
1740 }
1741
1742 ScheduledAction::ScheduledAction(const QString &_code, bool _singleShot)
1743 {
1744   //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
1745   //func = 0;
1746   //args = 0;
1747   code = _code;
1748   isFunction = false;
1749   singleShot = _singleShot;
1750 }
1751
1752 void ScheduledAction::execute(Window *window)
1753 {
1754   ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
1755
1756   interpreter->setProcessingTimerCallback(true);
1757
1758   //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
1759   if (isFunction) {
1760     if (func.implementsCall()) {
1761       // #### check this
1762       Q_ASSERT( window->m_part );
1763       if ( window->m_part )
1764       {
1765         KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
1766         ExecState *exec = interpreter->globalExec();
1767         Q_ASSERT( window == interpreter->globalObject().imp() );
1768         Object obj( window );
1769         Interpreter::lock();
1770         func.call(exec,obj,args); // note that call() creates its own execution state for the func call
1771         Interpreter::unlock();
1772         if ( exec->hadException() ) {
1773 #if APPLE_CHANGES
1774           Interpreter::lock();
1775           char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
1776           int lineNumber =  exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
1777           Interpreter::unlock();
1778           if (Interpreter::shouldPrintExceptions()) {
1779             printf("(timer):%s\n", message);
1780           }
1781           KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
1782 #endif
1783           exec->clearException();
1784         }
1785       }
1786     }
1787   }
1788   else {
1789     window->m_part->executeScript(code);
1790   }
1791
1792   // Update our document's rendering following the execution of the timeout callback.
1793   DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->m_part->document().handle());
1794   doc->updateRendering();
1795   
1796   interpreter->setProcessingTimerCallback(false);
1797 }
1798
1799 ScheduledAction::~ScheduledAction()
1800 {
1801   //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
1802 }
1803
1804 ////////////////////// WindowQObject ////////////////////////
1805
1806 WindowQObject::WindowQObject(Window *w)
1807   : parent(w)
1808 {
1809   //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
1810   part = parent->m_part;
1811   connect( parent->m_part, SIGNAL( destroyed() ),
1812            this, SLOT( parentDestroyed() ) );
1813 }
1814
1815 WindowQObject::~WindowQObject()
1816 {
1817   //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
1818   parentDestroyed(); // reuse same code
1819 }
1820
1821 void WindowQObject::parentDestroyed()
1822 {
1823   //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
1824   killTimers();
1825   QMapIterator<int,ScheduledAction*> it;
1826   for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1827     ScheduledAction *action = *it;
1828     //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
1829     delete action;
1830   }
1831   scheduledActions.clear();
1832 }
1833
1834 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
1835 {
1836   //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << endl;
1837   int id = startTimer(t);
1838   ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
1839   scheduledActions.insert(id, action);
1840   //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
1841   return id;
1842 }
1843
1844 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
1845 {
1846   Object objFunc = Object::dynamicCast( func );
1847   int id = startTimer(t);
1848   scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
1849   return id;
1850 }
1851
1852 QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
1853 {
1854     QMapIterator<int,ScheduledAction*> it;
1855
1856     QMap<int, KJS::ScheduledAction*>*pausedActions = new QMap<int, KJS::ScheduledAction*>;
1857     for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1858         int timerId = it.key();
1859         pauseTimer (timerId, key);
1860         pausedActions->insert(timerId, it.data());
1861     }
1862     scheduledActions.clear();
1863     return pausedActions;
1864 }
1865
1866 void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
1867 {
1868     QMapIterator<int,ScheduledAction*> it;
1869     for (it = sa->begin(); it != sa->end(); ++it) {
1870         int timerId = it.key();
1871         scheduledActions.insert(timerId, it.data());
1872     }
1873     sa->clear();
1874     resumeTimers (key, this);
1875 }
1876
1877 void WindowQObject::clearTimeout(int timerId, bool delAction)
1878 {
1879   //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
1880   killTimer(timerId);
1881   if (delAction) {
1882     QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
1883     if (it != scheduledActions.end()) {
1884       ScheduledAction *action = *it;
1885       scheduledActions.remove(it);
1886       delete action;
1887     }
1888   }
1889 }
1890
1891 void WindowQObject::timerEvent(QTimerEvent *e)
1892 {
1893   QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
1894   if (it != scheduledActions.end()) {
1895     ScheduledAction *action = *it;
1896     bool singleShot = action->singleShot;
1897     //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
1898
1899     // remove single shots installed by setTimeout()
1900     if (singleShot)
1901     {
1902       clearTimeout(e->timerId(),false);
1903       scheduledActions.remove(it);
1904     }
1905         
1906     if (!parent->part().isNull())
1907       action->execute(parent);
1908
1909     // It is important to test singleShot and not action->singleShot here - the
1910     // action could have been deleted already if not single shot and if the
1911     // JS code called by execute() calls clearTimeout().
1912     if (singleShot)
1913       delete action;
1914   } else
1915     kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
1916                     << " not found (" << scheduledActions.count() << " actions in map)" << endl;
1917 }
1918
1919 void WindowQObject::timeoutClose()
1920 {
1921   if (!parent->part().isNull())
1922   {
1923     //kdDebug(6070) << "WindowQObject::timeoutClose -> closing window" << endl;
1924     delete parent->m_part;
1925   }
1926 }
1927
1928 #if APPLE_CHANGES
1929 bool WindowQObject::hasTimeouts()
1930 {
1931     return scheduledActions.count();
1932 }
1933 #endif
1934
1935 Value FrameArray::get(ExecState *exec, const Identifier &p) const
1936 {
1937 #ifdef KJS_VERBOSE
1938   kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
1939 #endif
1940   if (part.isNull())
1941     return Undefined();
1942
1943   QPtrList<KParts::ReadOnlyPart> frames = part->frames();
1944   unsigned int len = frames.count();
1945   if (p == lengthPropertyName)
1946     return Number(len);
1947   else if (p== "location") // non-standard property, but works in NS and IE
1948   {
1949     Object obj = Object::dynamicCast( Window::retrieve( part ) );
1950     if ( !obj.isNull() )
1951       return obj.get( exec, "location" );
1952     return Undefined();
1953   }
1954
1955   // check for the name or number
1956   KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
1957   if (!frame) {
1958     bool ok;
1959     unsigned int i = p.toArrayIndex(&ok);
1960     if (ok && i < len)
1961       frame = frames.at(i);
1962   }
1963
1964   // we are potentially fetching a reference to a another Window object here.
1965   // i.e. we may be accessing objects from another interpreter instance.
1966   // Therefore we have to be a bit careful with memory managment.
1967   if (frame && frame->inherits("KHTMLPart")) {
1968     KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
1969     return Window::retrieve(khtml);
1970   }
1971
1972   return ObjectImp::get(exec, p);
1973 }
1974
1975 UString FrameArray::toString(ExecState *) const
1976 {
1977   return "[object FrameArray]";
1978 }
1979
1980 ////////////////////// Location Object ////////////////////////
1981
1982 const ClassInfo Location::info = { "Location", 0, 0, 0 };
1983 /*
1984 @begin LocationTable 11
1985   hash          Location::Hash          DontDelete
1986   host          Location::Host          DontDelete
1987   hostname      Location::Hostname      DontDelete
1988   href          Location::Href          DontDelete
1989   pathname      Location::Pathname      DontDelete
1990   port          Location::Port          DontDelete
1991   protocol      Location::Protocol      DontDelete
1992   search        Location::Search        DontDelete
1993   [[==]]        Location::EqualEqual    DontDelete|ReadOnly
1994   toString      Location::ToString      DontDelete|Function 0
1995   replace       Location::Replace       DontDelete|Function 1
1996   reload        Location::Reload        DontDelete|Function 0
1997 @end
1998 */
1999 IMPLEMENT_PROTOFUNC(LocationFunc)
2000 Location::Location(KHTMLPart *p) : m_part(p)
2001 {
2002   //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
2003 }
2004
2005 Location::~Location()
2006 {
2007   //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
2008 }
2009
2010 Value Location::get(ExecState *exec, const Identifier &p) const
2011 {
2012 #ifdef KJS_VERBOSE
2013   kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2014 #endif
2015
2016   if (m_part.isNull())
2017     return Undefined();
2018   
2019   const Window* window = Window::retrieveWindow(m_part);
2020   if (!window || !window->isSafeScript(exec))
2021       return Undefined();
2022
2023   KURL url = m_part->url();
2024   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2025   if (entry)
2026     switch (entry->value) {
2027     case Hash:
2028       return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
2029     case Host: {
2030       UString str = url.host();
2031       if (url.port())
2032         str += ":" + QString::number((int)url.port());
2033       return String(str);
2034       // Note: this is the IE spec. The NS spec swaps the two, it says
2035       // "The hostname property is the concatenation of the host and port properties, separated by a colon."
2036       // Bleh.
2037     }
2038     case Hostname:
2039       return String( url.host() );
2040     case Href:
2041       if (!url.hasPath())
2042         return String( url.prettyURL()+"/" );
2043       else
2044         return String( url.prettyURL() );
2045     case Pathname:
2046       return String( url.path().isEmpty() ? QString("/") : url.path() );
2047     case Port:
2048       return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
2049     case Protocol:
2050       return String( url.protocol()+":" );
2051     case Search:
2052       return String( url.query() );
2053     case EqualEqual: // [[==]]
2054       return String(toString(exec));
2055     case ToString:
2056       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2057     }
2058   // Look for overrides
2059   ValueImp * val = ObjectImp::getDirect(p);
2060   if (val)
2061     return Value(val);
2062   if (entry)
2063     switch (entry->value) {
2064     case Replace:
2065       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2066     case Reload:
2067       return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2068     }
2069
2070   return Undefined();
2071 }
2072
2073 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2074 {
2075 #ifdef KJS_VERBOSE
2076   kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
2077 #endif
2078   if (m_part.isNull())
2079     return;
2080
2081   QString str = v.toString(exec).qstring();
2082   KURL url = m_part->url();
2083   const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2084   if (entry)
2085     switch (entry->value) {
2086     case Href: {
2087       KHTMLPart* p = Window::retrieveActive(exec)->part();
2088       if ( p )
2089         url = p->htmlDocument().completeURL( str ).string();
2090       else
2091         url = str;
2092       break;
2093     }
2094     case Hash:
2095       url.setRef(str);
2096       break;
2097     case Host: {
2098       QString host = str.left(str.find(":"));
2099       QString port = str.mid(str.find(":")+1);
2100       url.setHost(host);
2101       url.setPort(port.toUInt());
2102       break;
2103     }
2104     case Hostname:
2105       url.setHost(str);
2106       break;
2107     case Pathname:
2108       url.setPath(str);
2109       break;
2110     case Port:
2111       url.setPort(str.toUInt());
2112       break;
2113     case Protocol:
2114       url.setProtocol(str);
2115       break;
2116     case Search:
2117       url.setQuery(str);
2118       break;
2119     }
2120   else {
2121     ObjectImp::put(exec, p, v, attr);
2122     return;
2123   }
2124   bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2125 #if APPLE_CHANGES
2126   // We want a new history item if this JS was called via a user gesture
2127   m_part->scheduleLocationChange(url.url(), !userGesture, userGesture);
2128 #else
2129   m_part->scheduleLocationChange(url.url(), false /*don't lock history*/, userGesture);
2130 #endif
2131 }
2132
2133 Value Location::toPrimitive(ExecState *exec, Type) const
2134 {
2135   return String(toString(exec));
2136 }
2137
2138 UString Location::toString(ExecState *) const
2139 {
2140   if (!m_part->url().hasPath())
2141     return m_part->url().prettyURL()+"/";
2142   else
2143     return m_part->url().prettyURL();
2144 }
2145
2146 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2147 {
2148   if (!thisObj.inherits(&Location::info)) {
2149     Object err = Error::create(exec,TypeError);
2150     exec->setException(err);
2151     return err;
2152   }
2153   Location *location = static_cast<Location *>(thisObj.imp());
2154   KHTMLPart *part = location->part();
2155   if (part) {
2156       
2157     Window* window = Window::retrieveWindow(part);
2158     if (!window->isSafeScript(exec) && id != Location::Replace)
2159         return Undefined();
2160       
2161     switch (id) {
2162     case Location::Replace:
2163     {
2164       QString str = args[0].toString(exec).qstring();
2165       KHTMLPart* p = Window::retrieveActive(exec)->part();
2166       if ( p ) {
2167         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2168         part->scheduleLocationChange(p->htmlDocument().completeURL(str).string(), true /*lock history*/, userGesture);
2169       }
2170       break;
2171     }
2172     case Location::Reload:
2173     {
2174       bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2175       part->scheduleLocationChange(part->url().url(), true/*lock history*/, userGesture);
2176       break;
2177     }
2178     case Location::ToString:
2179       return String(location->toString(exec));
2180     }
2181   } else
2182     kdDebug(6070) << "LocationFunc::tryExecute - no part!" << endl;
2183   return Undefined();
2184 }
2185
2186 ////////////////////// Selection Object ////////////////////////
2187
2188 const ClassInfo Selection::info = { "Selection", 0, 0, 0 };
2189 /*
2190 @begin SelectionTable 19
2191   anchorNode                Selection::AnchorNode                        DontDelete|ReadOnly
2192   anchorOffset              Selection::AnchorOffset                  DontDelete|ReadOnly
2193   focusNode                 Selection::FocusNode                         DontDelete|ReadOnly
2194   focusOffset               Selection::FocusOffset                       DontDelete|ReadOnly
2195   baseNode                  Selection::AnchorNode                        DontDelete|ReadOnly
2196   baseOffset                Selection::AnchorOffset              DontDelete|ReadOnly
2197   extentNode                Selection::FocusNode                 DontDelete|ReadOnly
2198   extentOffset              Selection::FocusOffset                       DontDelete|ReadOnly
2199   isCollapsed               Selection::IsCollapsed                       DontDelete|ReadOnly
2200   type                      Selection::_Type                     DontDelete|ReadOnly
2201   [[==]]                        Selection::EqualEqual                DontDelete|ReadOnly
2202   toString                  Selection::ToString                  DontDelete|Function 0
2203   collapse                  Selection::Collapse                  DontDelete|Function 2
2204   collapseToEnd             Selection::CollapseToEnd             DontDelete|Function 0
2205   collapseToStart           Selection::CollapseToStart           DontDelete|Function 0
2206   empty                     Selection::Empty                     DontDelete|Function 0
2207   setBaseAndExtent          Selection::SetBaseAndExtent          DontDelete|Function 4
2208   setPosition               Selection::SetPosition               DontDelete|Function 2
2209   modify                    Selection::Modify                    DontDelete|Function 3
2210 @end
2211 */
2212 IMPLEMENT_PROTOFUNC(SelectionFunc)
2213 Selection::Selection(KHTMLPart *p) : m_part(p)
2214 {
2215   //kdDebug(6070) << "Selection::Selection " << this << " m_part=" << (void*)m_part << endl;
2216 }
2217
2218 Selection::~Selection()
2219 {
2220   //kdDebug(6070) << "Selection::~Selection " << this << " m_part=" << (void*)m_part << endl;
2221 }
2222
2223 Value Selection::get(ExecState *exec, const Identifier &p) const
2224 {
2225 #ifdef KJS_VERBOSE
2226   kdDebug(6070) << "Selection::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2227 #endif
2228
2229   if (m_part.isNull())
2230     return Undefined();
2231   
2232   const Window* window = Window::retrieveWindow(m_part);
2233   if (!window || !window->isSafeScript(exec))
2234       return Undefined();
2235
2236   DocumentImpl *docimpl = m_part->xmlDocImpl();
2237   if (docimpl)
2238     docimpl->updateLayoutIgnorePendingStylesheets();
2239
2240   KURL url = m_part->url();
2241   const HashEntry *entry = Lookup::findEntry(&SelectionTable, p);
2242   if (entry)
2243     switch (entry->value) {
2244         case AnchorNode:
2245         case BaseNode:
2246             return getDOMNode(exec, Node(m_part->selection().base().node()));
2247         case AnchorOffset:
2248         case BaseOffset:
2249             return Number(m_part->selection().base().offset());
2250         case FocusNode:
2251         case ExtentNode:
2252             return getDOMNode(exec, Node(m_part->selection().extent().node()));
2253         case FocusOffset:
2254         case ExtentOffset:
2255             return Number(m_part->selection().extent().offset());
2256         case IsCollapsed:
2257             return Boolean(!m_part->selection().isRange());
2258         case _Type: {
2259             switch (m_part->selection().state()) {
2260                 case khtml::Selection::NONE:
2261                     return String("None");
2262                 case khtml::Selection::CARET:
2263                     return String("Caret");
2264                 case khtml::Selection::RANGE:
2265                     return String("Range");
2266             }
2267         }
2268         case EqualEqual:
2269             return String(toString(exec));
2270         case ToString:
2271           return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2272     }
2273     // Look for overrides
2274     ValueImp * val = ObjectImp::getDirect(p);
2275     if (val)
2276         return Value(val);
2277     if (entry)
2278         switch (entry->value) {
2279             case Collapse:
2280             case CollapseToEnd:
2281             case CollapseToStart:
2282             case Empty:
2283             case SetBaseAndExtent:
2284             case SetPosition:
2285             case Modify:
2286                 return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2287         }
2288
2289     return Undefined();
2290 }
2291
2292 void Selection::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2293 {
2294 }
2295
2296 Value Selection::toPrimitive(ExecState *exec, Type) const
2297 {
2298   return String(toString(exec));
2299 }
2300
2301 UString Selection::toString(ExecState *) const
2302 {
2303     if (!m_part->selection().isRange())
2304         return UString("");
2305     return UString(m_part->selection().toRange().toString());
2306 }
2307
2308 Value SelectionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2309 {
2310     if (!thisObj.inherits(&Selection::info)) {
2311         Object err = Error::create(exec,TypeError);
2312         exec->setException(err);
2313         return err;
2314     }
2315     Selection *selection = static_cast<Selection *>(thisObj.imp());
2316     KHTMLPart *part = selection->part();
2317     if (part) {
2318         DocumentImpl *docimpl = part->xmlDocImpl();
2319         if (docimpl)
2320             docimpl->updateLayoutIgnorePendingStylesheets();
2321             
2322         switch (id) {
2323             case Selection::Collapse:
2324                 TypingCommand::closeTyping(part->lastEditCommand());
2325                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec))));
2326                 break;
2327             case Selection::CollapseToEnd:
2328                 TypingCommand::closeTyping(part->lastEditCommand());
2329                 part->setSelection(khtml::Selection(part->selection().end()));
2330                 break;
2331             case Selection::CollapseToStart:
2332                 TypingCommand::closeTyping(part->lastEditCommand());
2333                 part->setSelection(khtml::Selection(part->selection().start()));
2334                 break;
2335             case Selection::Empty:
2336                 TypingCommand::closeTyping(part->lastEditCommand());
2337                 part->clearSelection();
2338                 break;
2339             case Selection::SetBaseAndExtent: {
2340                 TypingCommand::closeTyping(part->lastEditCommand());
2341                 Position base(KJS::toNode(args[0]).handle(), args[1].toInt32(exec));
2342                 Position extent(KJS::toNode(args[2]).handle(), args[3].toInt32(exec));
2343                 part->setSelection(khtml::Selection(base, extent));
2344                 break;
2345             }
2346             case Selection::SetPosition:
2347                 TypingCommand::closeTyping(part->lastEditCommand());
2348                 part->setSelection(khtml::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec))));
2349                 break;
2350             case Selection::Modify: {
2351                 TypingCommand::closeTyping(part->lastEditCommand());
2352                 khtml::Selection s(part->selection());
2353                 khtml::Selection::EAlter alter = khtml::Selection::MOVE;
2354                 if (args[0].toString(exec).string().lower() == "extend")
2355                     alter = khtml::Selection::EXTEND;
2356                 DOMString directionString = args[1].toString(exec).string().lower();
2357                 khtml::Selection::EDirection direction = khtml::Selection::FORWARD;
2358                 if (directionString == "backward")
2359                     direction = khtml::Selection::BACKWARD;
2360                 else if (directionString == "left")
2361                     direction = khtml::Selection::LEFT;
2362                 if (directionString == "right")
2363                     direction = khtml::Selection::RIGHT;
2364                 khtml::ETextGranularity granularity = khtml::CHARACTER;
2365                 DOMString granularityString = args[2].toString(exec).string().lower();
2366                 if (granularityString == "word")
2367                     granularity = khtml::WORD;
2368                 else if (granularityString == "line")
2369                     granularity = khtml::LINE;
2370                 else if (granularityString == "pargraph")
2371                     granularity = khtml::PARAGRAPH;
2372                 s.modify(alter, direction, granularity);
2373                 part->setSelection(s);
2374             }
2375         }
2376     }
2377
2378     return Undefined();
2379 }
2380
2381 ////////////////////// BarInfo Object ////////////////////////
2382
2383 const ClassInfo BarInfo::info = { "BarInfo", 0, 0, 0 };
2384 /*
2385 @begin BarInfoTable 1
2386   visible                BarInfo::Visible                        DontDelete|ReadOnly
2387 @end
2388 */
2389 BarInfo::BarInfo(ExecState *exec, KHTMLPart *p, Type barType) 
2390   : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype())
2391   , m_part(p)
2392   , m_type(barType)
2393 {
2394 }
2395
2396 BarInfo::~BarInfo()
2397 {
2398 }
2399
2400 Value BarInfo::get(ExecState *exec, const Identifier &p) const
2401 {
2402   if (m_part.isNull())
2403     return Undefined();
2404   
2405   const HashEntry *entry = Lookup::findEntry(&BarInfoTable, p);
2406   if (entry && entry->value == Visible) {
2407     switch (m_type) {
2408     case Locationbar:
2409 #if APPLE_CHANGES
2410       return Boolean(KWQ(m_part)->locationbarVisible());
2411 #endif
2412     case Menubar: 
2413 #if APPLE_CHANGES
2414       return Boolean(KWQ(m_part)->locationbarVisible());
2415 #endif
2416     case Personalbar:
2417 #if APPLE_CHANGES
2418       return Boolean(KWQ(m_part)->personalbarVisible());
2419 #endif
2420     case Scrollbars: 
2421 #if APPLE_CHANGES
2422       return Boolean(KWQ(m_part)->scrollbarsVisible());
2423 #endif
2424     case Statusbar:
2425 #if APPLE_CHANGES
2426       return Boolean(KWQ(m_part)->statusbarVisible());
2427 #endif
2428     case Toolbar:
2429 #if APPLE_CHANGES
2430       return Boolean(KWQ(m_part)->toolbarVisible());
2431 #endif
2432     default:
2433       return Boolean(false);
2434     }
2435   }
2436   
2437   return Undefined();
2438 }
2439
2440 void BarInfo::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2441 {
2442 }
2443
2444 ////////////////////// History Object ////////////////////////
2445
2446 const ClassInfo History::info = { "History", 0, 0, 0 };
2447 /*
2448 @begin HistoryTable 4
2449   length        History::Length         DontDelete|ReadOnly
2450   back          History::Back           DontDelete|Function 0
2451   forward       History::Forward        DontDelete|Function 0
2452   go            History::Go             DontDelete|Function 1
2453 @end
2454 */
2455 IMPLEMENT_PROTOFUNC(HistoryFunc)
2456
2457 Value History::get(ExecState *exec, const Identifier &p) const
2458 {
2459   return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
2460 }
2461
2462 Value History::getValueProperty(ExecState *, int token) const
2463 {
2464   switch (token) {
2465   case Length:
2466   {
2467     KParts::BrowserExtension *ext = part->browserExtension();
2468     if ( !ext )
2469       return Number( 0 );
2470
2471     KParts::BrowserInterface *iface = ext->browserInterface();
2472     if ( !iface )
2473       return Number( 0 );
2474
2475     QVariant length = iface->property( "historyLength" );
2476
2477     if ( length.type() != QVariant::UInt )
2478       return Number( 0 );
2479
2480     return Number( length.toUInt() );
2481   }
2482   default:
2483     kdWarning() << "Unhandled token in History::getValueProperty : " << token << endl;
2484     return Undefined();
2485   }
2486 }
2487
2488 UString History::toString(ExecState *exec) const
2489 {
2490   return "[object History]";
2491 }
2492
2493 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2494 {
2495   if (!thisObj.inherits(&History::info)) {
2496     Object err = Error::create(exec,TypeError);
2497     exec->setException(err);
2498     return err;
2499   }
2500   History *history = static_cast<History *>(thisObj.imp());
2501
2502   int steps;
2503   switch (id) {
2504   case History::Back:
2505     steps = -1;
2506     break;
2507   case History::Forward:
2508     steps = 1;
2509     break;
2510   case History::Go:
2511     steps = args[0].toInt32(exec);
2512     break;
2513   default:
2514     return Undefined();
2515   }
2516
2517   history->part->scheduleHistoryNavigation(steps);
2518   return Undefined();
2519 }
2520
2521 /////////////////////////////////////////////////////////////////////////////
2522
2523 #ifdef Q_WS_QWS
2524
2525 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
2526
2527 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
2528 {
2529   if ( p.qstring().startsWith( "goHistory" ) ) return false;
2530
2531   return true;
2532 }
2533
2534 Value Konqueror::get(ExecState *exec, const Identifier &p) const
2535 {
2536   if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
2537     return Undefined();
2538
2539   KParts::BrowserExtension *ext = part->browserExtension();
2540   if ( ext ) {
2541     KParts::BrowserInterface *iface = ext->browserInterface();
2542     if ( iface ) {
2543       QVariant prop = iface->property( p.qstring().latin1() );
2544
2545       if ( prop.isValid() ) {
2546         switch( prop.type() ) {
2547         case QVariant::Int:
2548           return Number( prop.toInt() );
2549         case QVariant::String:
2550           return String( prop.toString() );
2551         default:
2552           break;
2553         }
2554       }
2555     }
2556   }
2557
2558   return /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
2559 }
2560
2561 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
2562 {
2563   KParts::BrowserExtension *ext = konqueror->part->browserExtension();
2564
2565   if(!ext)
2566     return Undefined();
2567
2568   KParts::BrowserInterface *iface = ext->browserInterface();
2569
2570   if ( !iface )
2571     return Undefined();
2572
2573   QCString n = m_name.data();
2574   n += "()";
2575   iface->callMethod( n.data(), QVariant() );
2576
2577   return Undefined();
2578 }
2579
2580 UString Konqueror::toString(ExecState *) const
2581 {
2582   return UString("[object Konqueror]");
2583 }
2584
2585 #endif
2586 /////////////////////////////////////////////////////////////////////////////
2587
2588 #include "kjs_window.moc"
2589