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