1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 2000 Harri Porten (porten@kde.org)
5 * Copyright (C) 2003 Apple Computer, Inc.
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.
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.
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
22 #include <qstylesheet.h>
24 #include <qinputdialog.h>
25 #include <qpaintdevicemetrics.h>
26 #include <qapplication.h>
28 #include <kmessagebox.h>
30 #include <kparts/browserinterface.h>
32 #include <kwinmodule.h>
36 #include "rendering/render_canvas.h"
39 #include "KWQLogging.h"
40 #include "KWQKConfigBase.h"
42 #include <kjs/collector.h>
43 #include "kjs_proxy.h"
44 #include "kjs_window.h"
45 #include "kjs_navigator.h"
47 #include "kjs_range.h"
48 #include "kjs_traversal.h"
50 #include "kjs_events.h"
51 #include "xmlhttprequest.h"
52 #include "xmlserializer.h"
54 #include "khtmlview.h"
55 #include "khtml_part.h"
56 #include "dom/dom_string.h"
57 #include "dom/dom_node.h"
58 #include "editing/htmlediting.h"
59 #include "xml/dom2_eventsimpl.h"
60 #include "xml/dom_docimpl.h"
61 #include "xml/dom_position.h"
62 #include "xml/dom_selection.h"
63 #include "html/html_documentimpl.h"
65 using DOM::DocumentImpl;
69 using khtml::TypingCommand;
75 ////////////////////// History Object ////////////////////////
77 class History : public ObjectImp {
78 friend class HistoryFunc;
80 History(ExecState *exec, KHTMLPart *p)
81 : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
82 virtual Value get(ExecState *exec, const Identifier &propertyName) const;
83 Value getValueProperty(ExecState *exec, int token) const;
84 virtual const ClassInfo* classInfo() const { return &info; }
85 static const ClassInfo info;
86 enum { Back, Forward, Go, Length };
87 virtual UString toString(ExecState *exec) const;
89 QGuardedPtr<KHTMLPart> part;
92 class FrameArray : public ObjectImp {
94 FrameArray(ExecState *exec, KHTMLPart *p)
95 : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
96 virtual Value get(ExecState *exec, const Identifier &propertyName) const;
97 virtual UString toString(ExecState *exec) const;
99 QGuardedPtr<KHTMLPart> part;
103 class KonquerorFunc : public DOMFunction {
105 KonquerorFunc(const Konqueror* k, const char* name)
106 : DOMFunction(), konqueror(k), m_name(name) { }
107 virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
110 const Konqueror* konqueror;
116 #include "kjs_window.lut.h"
118 ////////////////////// Screen Object ////////////////////////
120 // table for screen object
123 height Screen::Height DontEnum|ReadOnly
124 width Screen::Width DontEnum|ReadOnly
125 colorDepth Screen::ColorDepth DontEnum|ReadOnly
126 pixelDepth Screen::PixelDepth DontEnum|ReadOnly
127 availLeft Screen::AvailLeft DontEnum|ReadOnly
128 availTop Screen::AvailTop DontEnum|ReadOnly
129 availHeight Screen::AvailHeight DontEnum|ReadOnly
130 availWidth Screen::AvailWidth DontEnum|ReadOnly
134 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
136 // We set the object prototype so that toString is implemented
137 Screen::Screen(ExecState *exec)
138 : ObjectImp(exec->lexicalInterpreter()->builtinObjectPrototype()) {}
140 Value Screen::get(ExecState *exec, const Identifier &p) const
143 kdDebug(6070) << "Screen::get " << p.qstring() << endl;
145 return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
148 Value Screen::getValueProperty(ExecState *exec, int token) const
151 QWidget *thisWidget = Window::retrieveActive(exec)->part()->view();
152 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(thisWidget));
156 return Number(sg.height());
158 return Number(sg.width());
161 QPaintDeviceMetrics m(QApplication::desktop());
162 return Number(m.depth());
165 QRect clipped = info.workArea().intersect(sg);
166 return Number(clipped.x()-sg.x());
169 QRect clipped = info.workArea().intersect(sg);
170 return Number(clipped.y()-sg.y());
173 QRect clipped = info.workArea().intersect(sg);
174 return Number(clipped.height());
177 QRect clipped = info.workArea().intersect(sg);
178 return Number(clipped.width());
181 kdWarning() << "Screen::getValueProperty unhandled token " << token << endl;
186 ////////////////////// Window Object ////////////////////////
188 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 };
191 @begin WindowTable 91
192 closed Window::Closed DontDelete|ReadOnly
193 crypto Window::Crypto DontDelete|ReadOnly
194 defaultStatus Window::DefaultStatus DontDelete
195 defaultstatus Window::DefaultStatus DontDelete
196 status Window::Status DontDelete
197 document Window::Document DontDelete|ReadOnly
198 Node Window::Node DontDelete
199 Event Window::EventCtor DontDelete
200 Range Window::Range DontDelete
201 NodeFilter Window::NodeFilter DontDelete
202 DOMException Window::DOMException DontDelete
203 CSSRule Window::CSSRule DontDelete
204 frames Window::Frames DontDelete|ReadOnly
205 history Window::_History DontDelete|ReadOnly
206 event Window::Event DontDelete
207 innerHeight Window::InnerHeight DontDelete|ReadOnly
208 innerWidth Window::InnerWidth DontDelete|ReadOnly
209 length Window::Length DontDelete|ReadOnly
210 location Window::_Location DontDelete
211 name Window::Name DontDelete
212 navigator Window::_Navigator DontDelete|ReadOnly
213 clientInformation Window::ClientInformation DontDelete|ReadOnly
214 konqueror Window::_Konqueror DontDelete|ReadOnly
215 offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly
216 opener Window::Opener DontDelete|ReadOnly
217 outerHeight Window::OuterHeight DontDelete|ReadOnly
218 outerWidth Window::OuterWidth DontDelete|ReadOnly
219 pageXOffset Window::PageXOffset DontDelete|ReadOnly
220 pageYOffset Window::PageYOffset DontDelete|ReadOnly
221 parent Window::Parent DontDelete|ReadOnly
222 personalbar Window::Personalbar DontDelete|ReadOnly
223 screenX Window::ScreenX DontDelete|ReadOnly
224 screenY Window::ScreenY DontDelete|ReadOnly
225 screenLeft Window::ScreenLeft DontDelete|ReadOnly
226 screenTop Window::ScreenTop DontDelete|ReadOnly
227 scrollbars Window::Scrollbars DontDelete|ReadOnly
228 scroll Window::Scroll DontDelete|Function 2
229 scrollBy Window::ScrollBy DontDelete|Function 2
230 scrollTo Window::ScrollTo DontDelete|Function 2
231 scrollX Window::ScrollX DontDelete|ReadOnly
232 scrollY Window::ScrollY DontDelete|ReadOnly
233 moveBy Window::MoveBy DontDelete|Function 2
234 moveTo Window::MoveTo DontDelete|Function 2
235 resizeBy Window::ResizeBy DontDelete|Function 2
236 resizeTo Window::ResizeTo DontDelete|Function 2
237 self Window::Self DontDelete|ReadOnly
238 window Window::_Window DontDelete|ReadOnly
239 top Window::Top DontDelete|ReadOnly
240 screen Window::_Screen DontDelete|ReadOnly
241 Image Window::Image DontDelete|ReadOnly
242 Option Window::Option DontDelete|ReadOnly
243 XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly
244 XMLSerializer Window::XMLSerializer DontDelete|ReadOnly
245 alert Window::Alert DontDelete|Function 1
246 confirm Window::Confirm DontDelete|Function 1
247 prompt Window::Prompt DontDelete|Function 2
248 open Window::Open DontDelete|Function 3
249 print Window::Print DontDelete|Function 2
250 setTimeout Window::SetTimeout DontDelete|Function 2
251 clearTimeout Window::ClearTimeout DontDelete|Function 1
252 focus Window::Focus DontDelete|Function 0
253 getSelection Window::GetSelection DontDelete|Function 0
254 blur Window::Blur DontDelete|Function 0
255 close Window::Close DontDelete|Function 0
256 setInterval Window::SetInterval DontDelete|Function 2
257 clearInterval Window::ClearInterval DontDelete|Function 1
258 captureEvents Window::CaptureEvents DontDelete|Function 0
259 releaseEvents Window::ReleaseEvents DontDelete|Function 0
260 # Warning, when adding a function to this object you need to add a case in Window::get
261 addEventListener Window::AddEventListener DontDelete|Function 3
262 removeEventListener Window::RemoveEventListener DontDelete|Function 3
263 onabort Window::Onabort DontDelete
264 onblur Window::Onblur DontDelete
265 onchange Window::Onchange DontDelete
266 onclick Window::Onclick DontDelete
267 ondblclick Window::Ondblclick DontDelete
268 ondragdrop Window::Ondragdrop DontDelete
269 onerror Window::Onerror DontDelete
270 onfocus Window::Onfocus DontDelete
271 onkeydown Window::Onkeydown DontDelete
272 onkeypress Window::Onkeypress DontDelete
273 onkeyup Window::Onkeyup DontDelete
274 onload Window::Onload DontDelete
275 onmousedown Window::Onmousedown DontDelete
276 onmousemove Window::Onmousemove DontDelete
277 onmouseout Window::Onmouseout DontDelete
278 onmouseover Window::Onmouseover DontDelete
279 onmouseup Window::Onmouseup DontDelete
280 onmove Window::Onmove DontDelete
281 onreset Window::Onreset DontDelete
282 onresize Window::Onresize DontDelete
283 onscroll Window::Onscroll DontDelete
284 onsearch Window::Onsearch DontDelete
285 onselect Window::Onselect DontDelete
286 onsubmit Window::Onsubmit DontDelete
287 onunload Window::Onunload DontDelete
290 IMPLEMENT_PROTOFUNC(WindowFunc)
292 Window::Window(KHTMLPart *p)
293 : ObjectImp(/*no proto*/), m_part(p), screen(0), history(0), frames(0), loc(0), m_selection(0), m_evt(0)
295 winq = new WindowQObject(this);
296 //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
301 kdDebug(6070) << "Window::~Window this=" << this << " part=" << m_part << endl;
305 Window *Window::retrieveWindow(KHTMLPart *p)
307 Object obj = Object::dynamicCast( retrieve( p ) );
309 // obj should never be null, except when javascript has been disabled in that part.
310 if ( p && p->jScriptEnabled() )
312 assert( !obj.isNull() );
314 assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
318 if ( obj.isNull() ) // JS disabled
320 return static_cast<KJS::Window*>(obj.imp());
323 Window *Window::retrieveActive(ExecState *exec)
325 ValueImp *imp = exec->dynamicInterpreter()->globalObject().imp();
328 assert( dynamic_cast<KJS::Window*>(imp) );
330 return static_cast<KJS::Window*>(imp);
333 Value Window::retrieve(KHTMLPart *p)
336 KJSProxy *proxy = KJSProxy::proxy( p );
339 kdDebug(6070) << "Window::retrieve part=" << p << " interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
341 return proxy->interpreter()->globalObject(); // the Global object is the "window"
343 return Undefined(); // This can happen with JS disabled on the domain of that window
346 Location *Window::location() const
349 const_cast<Window*>(this)->loc = new Location(m_part);
353 Selection *Window::selection() const
356 const_cast<Window*>(this)->m_selection = new Selection(m_part);
360 // reference our special objects during garbage collection
364 if (screen && !screen->marked())
366 if (history && !history->marked())
368 if (frames && !frames->marked())
370 //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
371 if (loc && !loc->marked())
373 if (m_selection && !m_selection->marked())
377 bool Window::hasProperty(ExecState * /*exec*/, const Identifier &/*p*/) const
379 //fprintf( stderr, "Window::hasProperty: always saying true\n" );
381 // emulate IE behaviour: it doesn't throw exceptions when undeclared
382 // variables are used. Returning true here will lead to get() returning
383 // 'undefined' in those cases.
387 UString Window::toString(ExecState *) const
389 return "[object Window]";
392 Value Window::get(ExecState *exec, const Identifier &p) const
395 kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
398 return Boolean(m_part.isNull());
400 // we don't want any operations on a closed window
404 // Look for overrides first
405 ValueImp * val = ObjectImp::getDirect(p);
407 //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
408 if (isSafeScript(exec))
412 const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
415 //kdDebug(6070) << "token: " << entry->value << endl;
416 switch( entry->value ) {
418 return Undefined(); // ###
420 return String(UString(m_part->jsDefaultStatusBarText()));
422 return String(UString(m_part->jsStatusBarText()));
424 if (isSafeScript(exec))
426 if (m_part->document().isNull()) {
428 KWQ(m_part)->createEmptyDocument();
430 kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
432 m_part->write("<HTML><BODY>");
435 Value val = getDOMNode(exec,m_part->document());
441 return getNodeConstructor(exec);
443 return getRangeConstructor(exec);
445 return getNodeFilterConstructor(exec);
447 return getDOMExceptionConstructor(exec);
449 return getCSSRuleConstructor(exec);
451 return getEventConstructor(exec);
453 return Value(frames ? frames :
454 (const_cast<Window*>(this)->frames = new FrameArray(exec,m_part)));
456 return Value(history ? history :
457 (const_cast<Window*>(this)->history = new History(exec,m_part)));
461 return getDOMEvent(exec,*m_evt);
464 kdWarning(6070) << "window(" << this << "," << m_part->name() << ").event, no event!" << endl;
472 return Number(m_part->view()->visibleHeight());
477 return Number(m_part->view()->visibleWidth());
479 return Number(m_part->frames().count());
481 return Value(location());
483 return String(m_part->name());
485 case ClientInformation: {
486 // Store the navigator in the object so we get the same one each time.
487 Navigator *n = new Navigator(exec, m_part);
488 const_cast<Window *>(this)->putDirect("navigator", n, DontDelete|ReadOnly);
489 const_cast<Window *>(this)->putDirect("clientInformation", n, DontDelete|ReadOnly);
494 return Value(new Konqueror(m_part));
496 case OffscreenBuffering:
497 return Boolean(true);
499 if (!m_part->opener())
500 return Null(); // ### a null Window might be better, but == null
501 else // doesn't work yet
502 return retrieve(m_part->opener());
508 KWin::Info inf = KWin::info(m_part->view()->topLevelWidget()->winId());
509 return Number(entry->value == OuterHeight ?
510 inf.geometry.height() : inf.geometry.width());
516 return Number(m_part->view()->contentsX());
521 return Number(m_part->view()->contentsY());
523 return Value(retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part));
525 return Undefined(); // ###
530 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
531 return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
537 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(m_part->view()));
538 return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
544 return Number(m_part->view()->contentsX());
550 return Number(m_part->view()->contentsY());
553 return Undefined(); // ###
556 return Value(retrieve(m_part));
558 KHTMLPart *p = m_part;
559 while (p->parentPart())
561 return Value(retrieve(p));
564 return Value(screen ? screen :
565 (const_cast<Window*>(this)->screen = new Screen(exec)));
567 return Value(new ImageConstructorImp(exec, m_part->document()));
569 return Value(new OptionConstructorImp(exec, m_part->document()));
571 return Value(new XMLHttpRequestConstructorImp(exec, m_part->document()));
573 return Value(new XMLSerializerConstructorImp(exec));
584 case Scroll: // compatibility
591 return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
594 case AddEventListener:
595 case RemoveEventListener:
601 if (isSafeScript(exec))
602 return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
606 if (isSafeScript(exec))
607 return getListener(exec,DOM::EventImpl::ABORT_EVENT);
611 if (isSafeScript(exec))
612 return getListener(exec,DOM::EventImpl::BLUR_EVENT);
616 if (isSafeScript(exec))
617 return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
621 if (isSafeScript(exec))
622 return getListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT);
626 if (isSafeScript(exec))
627 return getListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT);
631 if (isSafeScript(exec))
632 return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
636 if (isSafeScript(exec))
637 return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT);
641 if (isSafeScript(exec))
642 return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
646 if (isSafeScript(exec))
647 return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
651 if (isSafeScript(exec))
652 return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
656 if (isSafeScript(exec))
657 return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
661 if (isSafeScript(exec))
662 return getListener(exec,DOM::EventImpl::LOAD_EVENT);
666 if (isSafeScript(exec))
667 return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
671 if (isSafeScript(exec))
672 return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
676 if (isSafeScript(exec))
677 return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
681 if (isSafeScript(exec))
682 return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
686 if (isSafeScript(exec))
687 return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
691 if (isSafeScript(exec))
692 return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
696 if (isSafeScript(exec))
697 return getListener(exec,DOM::EventImpl::RESET_EVENT);
701 if (isSafeScript(exec))
702 return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
706 if (isSafeScript(exec))
707 return getListener(exec,DOM::EventImpl::SCROLL_EVENT);
712 if (isSafeScript(exec))
713 return getListener(exec,DOM::EventImpl::SEARCH_EVENT);
718 if (isSafeScript(exec))
719 return getListener(exec,DOM::EventImpl::SELECT_EVENT);
723 if (isSafeScript(exec))
724 return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
728 if (isSafeScript(exec))
729 return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
735 KHTMLPart *kp = m_part->findFrame( p.qstring() );
737 return Value(retrieve(kp));
739 // allow window[1] or parent[1] etc. (#56983)
741 unsigned int i = p.toArrayIndex(&ok);
743 QPtrList<KParts::ReadOnlyPart> frames = m_part->frames();
744 unsigned int len = frames.count();
746 KParts::ReadOnlyPart* frame = frames.at(i);
747 if (frame && frame->inherits("KHTMLPart")) {
748 KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
749 return Window::retrieve(khtml);
754 // allow shortcuts like 'Image1' instead of document.images.Image1
755 if (isSafeScript(exec) &&
756 m_part->document().isHTMLDocument()) { // might be XML
757 DOM::HTMLCollection coll = m_part->htmlDocument().all();
758 DOM::HTMLElement element = coll.namedItem(p.string());
759 if (!element.isNull()) {
760 return getDOMNode(exec,element);
764 // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
765 // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
767 kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
772 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
774 // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
775 // If yes, save time and jump directly to ObjectImp.
776 if ( (attr != None && attr != DontDelete)
777 // Same thing if we have a local override (e.g. "var location")
778 || ( ObjectImp::getDirect(propertyName) && isSafeScript(exec)) )
780 ObjectImp::put( exec, propertyName, value, attr );
784 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
788 kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
790 switch( entry->value ) {
792 String s = value.toString(exec);
793 m_part->setJSStatusBarText(s.value().qstring());
796 case DefaultStatus: {
797 String s = value.toString(exec);
798 m_part->setJSDefaultStatusBarText(s.value().qstring());
802 KHTMLPart* p = Window::retrieveActive(exec)->m_part;
804 QString dstUrl = p->htmlDocument().completeURL(value.toString(exec).string()).string();
805 if (dstUrl.find("javascript:", 0, false) || isSafeScript(exec))
807 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
809 // We want a new history item if this JS was called via a user gesture
810 m_part->scheduleRedirection(0, dstUrl, !userGesture, userGesture);
812 m_part->scheduleRedirection(0,
814 false /*don't lock history*/, userGesture);
821 if (isSafeScript(exec))
822 setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
825 if (isSafeScript(exec))
826 setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
829 if (isSafeScript(exec))
830 setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
833 if (isSafeScript(exec))
834 setListener(exec,DOM::EventImpl::KHTML_CLICK_EVENT,value);
837 if (isSafeScript(exec))
838 setListener(exec,DOM::EventImpl::KHTML_DBLCLICK_EVENT,value);
841 if (isSafeScript(exec))
842 setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
845 if (isSafeScript(exec))
846 setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value);
849 if (isSafeScript(exec))
850 setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
853 if (isSafeScript(exec))
854 setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
857 if (isSafeScript(exec))
858 setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
861 if (isSafeScript(exec))
862 setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
865 if (isSafeScript(exec))
866 setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
869 if (isSafeScript(exec))
870 setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
873 if (isSafeScript(exec))
874 setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
877 if (isSafeScript(exec))
878 setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
881 if (isSafeScript(exec))
882 setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
885 if (isSafeScript(exec))
886 setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
889 if (isSafeScript(exec))
890 setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
893 if (isSafeScript(exec))
894 setListener(exec,DOM::EventImpl::RESET_EVENT,value);
897 if (isSafeScript(exec))
898 setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
901 if (isSafeScript(exec))
902 setListener(exec,DOM::EventImpl::SCROLL_EVENT,value);
906 if (isSafeScript(exec))
907 setListener(exec,DOM::EventImpl::SEARCH_EVENT,value);
911 if (isSafeScript(exec))
912 setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
915 if (isSafeScript(exec))
916 setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
919 if (isSafeScript(exec))
920 setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
923 if (isSafeScript(exec))
925 m_part->setName( value.toString(exec).qstring() );
927 m_part->setName( value.toString(exec).qstring().local8Bit().data() );
934 if (isSafeScript(exec)) {
935 //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
936 ObjectImp::put(exec, propertyName, value, attr);
940 bool Window::toBoolean(ExecState *) const
942 return !m_part.isNull();
945 int Window::installTimeout(const UString &handler, int t, bool singleShot)
947 return winq->installTimeout(handler, t, singleShot);
950 int Window::installTimeout(const Value &function, List &args, int t, bool singleShot)
952 return winq->installTimeout(function, args, t, singleShot);
955 void Window::clearTimeout(int timerId)
957 winq->clearTimeout(timerId);
961 bool Window::hasTimeouts()
963 return winq->hasTimeouts();
966 QMap<int, ScheduledAction*> *Window::pauseTimeouts(const void *key)
968 return winq->pauseTimeouts(key);
971 void Window::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
973 return winq->resumeTimeouts(sa, key);
977 void Window::scheduleClose()
979 kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl;
982 KWQ(m_part)->scheduleClose();
984 QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
988 static bool shouldLoadAsEmptyDocument(const KURL &url)
990 return url.protocol().lower() == "about" || url.isEmpty();
993 bool Window::isSafeScript(ExecState *exec) const
995 if (m_part.isNull()) { // part deleted ? can't grant access
996 kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
999 KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
1001 kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
1004 if ( activePart == m_part ) // Not calling from another frame, no problem.
1007 // JS may be attempting to access the "window" object, which should be valid,
1008 // even if the document hasn't been constructed yet. If the document doesn't
1009 // exist yet allow JS to access the window object.
1010 if (!m_part->xmlDocImpl())
1013 DOM::DocumentImpl* thisDocument = m_part->xmlDocImpl();
1014 DOM::DocumentImpl* actDocument = activePart->xmlDocImpl();
1017 kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
1021 DOM::DOMString actDomain = actDocument->domain();
1023 // Always allow local pages to execute any JS.
1024 if (actDomain.isNull())
1027 DOM::DOMString thisDomain = thisDocument->domain();
1029 // if this document is being initially loaded as empty by its parent
1030 // or opener, allow access from any document in the same domain as
1031 // the parent or opener.
1032 if (shouldLoadAsEmptyDocument(m_part->url())) {
1033 KHTMLPart *ancestorPart = m_part->opener() ? m_part->opener() : m_part->parentPart();
1034 while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
1035 ancestorPart = ancestorPart->parentPart();
1039 thisDomain = ancestorPart->docImpl()->domain();
1042 //kdDebug(6070) << "current domain:" << actDomain.string() << ", frame domain:" << thisDomain.string() << endl;
1043 if ( actDomain == thisDomain )
1047 if (Interpreter::shouldPrintExceptions()) {
1048 printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n",
1049 thisDocument->URL().latin1(), actDocument->URL().latin1());
1051 message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n",
1052 thisDocument->URL().latin1(), actDocument->URL().latin1());
1053 KWQ(m_part)->addMessageToConsole(message, 1, QString()); //fixme: provide a real line number and sourceurl
1057 kdWarning(6070) << "Javascript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
1061 void Window::setListener(ExecState *exec, int eventId, Value func)
1063 if (!isSafeScript(exec))
1065 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1069 doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
1072 Value Window::getListener(ExecState *exec, int eventId) const
1074 if (!isSafeScript(exec))
1076 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
1080 DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
1081 if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
1082 return static_cast<JSEventListener*>(listener)->listenerObj();
1088 JSEventListener *Window::getJSEventListener(const Value& val, bool html)
1090 // This function is so hot that it's worth coding it directly with imps.
1091 if (val.type() != ObjectType)
1093 ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
1095 JSEventListener *existingListener = jsEventListeners[listenerObject];
1096 if (existingListener)
1097 return existingListener;
1099 // Note that the JSEventListener constructor adds it to our jsEventListeners list
1100 return new JSEventListener(Object(listenerObject), Object(this), html);
1103 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, bool html, int lineNumber)
1105 return new JSLazyEventListener(code, Object(this), html, lineNumber);
1108 void Window::clear( ExecState *exec )
1110 KJS::Interpreter::lock();
1111 kdDebug(6070) << "Window::clear " << this << endl;
1113 winq = new WindowQObject(this);;
1114 // Get rid of everything, those user vars could hold references to DOM nodes
1115 deleteAllProperties( exec );
1116 // Really delete those properties, so that the DOM nodes get deref'ed
1117 KJS::Collector::collect();
1118 // Now recreate a working global object for the next URL that will use us
1119 KJS::Interpreter *interpreter = KJSProxy::proxy( m_part )->interpreter();
1120 interpreter->initGlobalObject();
1121 KJS::Interpreter::unlock();
1124 void Window::setCurrentEvent( DOM::Event *evt )
1127 //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
1130 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
1132 if (!thisObj.inherits(&Window::info)) {
1133 Object err = Error::create(exec,TypeError);
1134 exec->setException(err);
1137 Window *window = static_cast<Window *>(thisObj.imp());
1140 KHTMLPart *part = window->m_part;
1144 KHTMLView *widget = part->view();
1146 UString s = v.toString(exec);
1151 if (part && part->xmlDocImpl())
1152 part->xmlDocImpl()->updateRendering();
1154 KWQ(part)->runJavaScriptAlert(str);
1156 KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
1159 case Window::Confirm:
1160 if (part && part->xmlDocImpl())
1161 part->xmlDocImpl()->updateRendering();
1163 return Boolean(KWQ(part)->runJavaScriptConfirm(str));
1165 return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
1166 i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
1168 case Window::Prompt:
1169 if (part && part->xmlDocImpl())
1170 part->xmlDocImpl()->updateRendering();
1173 ok = KWQ(part)->runJavaScriptPrompt(str, args.size() >= 2 ? args[1].toString(exec).qstring() : QString::null, str2);
1175 if (args.size() >= 2)
1176 str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1177 QStyleSheet::convertFromPlainText(str),
1179 args[1].toString(exec).qstring(), &ok);
1181 str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
1182 QStyleSheet::convertFromPlainText(str),
1184 QString::null, &ok);
1187 return String(str2);
1192 KConfig *config = new KConfig("konquerorrc");
1193 config->setGroup("Java/JavaScript Settings");
1195 int policy = config->readUnsignedNumEntry( "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1197 int policy = config->readUnsignedNumEntry( part->settings(), "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
1200 if ( policy == 1 ) {
1202 if ( KMessageBox::questionYesNo(widget,
1203 i18n( "This site is trying to open up a new browser "
1204 "window using Javascript.\n"
1205 "Do you want to allow this?" ),
1206 i18n( "Confirmation: Javascript Popup" ) ) == KMessageBox::Yes )
1209 } else if ( policy == 3 ) // smart
1211 // window.open disabled unless from a key/mouse event
1212 if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture())
1218 LOG(PopupBlocking, "Allowed JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1220 LOG(PopupBlocking, "Blocked JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
1225 QString frameName = !args[1].isNull() && args[1].type() != UndefinedType ?
1226 args[1].toString(exec).qstring()
1227 : QString("_blank");
1229 if ( policy != 0 && !(part->findFrame(frameName) || frameName == "_top" || frameName == "_parent" || frameName == "_self")) {
1232 if (v.type() == UndefinedType)
1235 KParts::WindowArgs winargs;
1237 // scan feature argument
1240 if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
1241 features = v.toString(exec).qstring();
1242 // specifying window params means false defaults
1243 winargs.menuBarVisible = false;
1244 winargs.toolBarsVisible = false;
1245 winargs.statusBarVisible = false;
1247 winargs.scrollbarsVisible = true;
1249 QStringList flist = QStringList::split(',', features);
1250 QStringList::ConstIterator it = flist.begin();
1251 while (it != flist.end()) {
1254 int pos = s.find('=');
1256 key = s.left(pos).stripWhiteSpace().lower();
1257 val = s.mid(pos + 1).stripWhiteSpace().lower();
1258 int spacePos = val.find(' ');
1259 if (spacePos != -1) {
1260 val = val.left(spacePos);
1263 int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
1265 QRect screen = QApplication::desktop()->screenGeometry(scnum);
1266 if (key == "left" || key == "screenx") {
1268 double d = val.toDouble(&ok);
1271 if (d < screen.x() || d > screen.right())
1272 d = screen.x(); // only safe choice until size is determined
1275 winargs.xSet = true;
1278 } else if (key == "top" || key == "screeny") {
1280 double d = val.toDouble(&ok);
1283 if (d < screen.y() || d > screen.bottom())
1284 d = screen.y(); // only safe choice until size is determined
1287 winargs.ySet = true;
1290 } else if (key == "height") {
1292 double d = val.toDouble(&ok);
1295 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1297 if (d > screen.height()) // should actually check workspace
1298 d = screen.height();
1301 winargs.height = (int)d;
1303 winargs.heightSet = true;
1306 } else if (key == "width") {
1308 double d = val.toDouble(&ok);
1311 d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
1313 if (d > screen.width()) // should actually check workspace
1317 winargs.width = (int)d;
1319 winargs.widthSet = true;
1327 // leaving away the value gives true
1328 key = s.stripWhiteSpace().lower();
1332 if (key == "menubar")
1333 winargs.menuBarVisible = (val == "1" || val == "yes");
1334 else if (key == "toolbar")
1335 winargs.toolBarsVisible = (val == "1" || val == "yes");
1336 else if (key == "location") // ### missing in WindowArgs
1337 winargs.toolBarsVisible = (val == "1" || val == "yes");
1338 else if (key == "status" || key == "statusbar")
1339 winargs.statusBarVisible = (val == "1" || val == "yes");
1340 else if (key == "resizable")
1341 winargs.resizable = (val == "1" || val == "yes");
1342 else if (key == "fullscreen")
1343 winargs.fullscreen = (val == "1" || val == "yes");
1345 else if (key == "scrollbars")
1346 winargs.scrollbarsVisible = !(val == "0" || val == "no");
1351 // prepare arguments
1355 KHTMLPart* p = Window::retrieveActive(exec)->m_part;
1357 url = p->htmlDocument().completeURL(str).string();
1360 KParts::URLArgs uargs;
1361 uargs.frameName = frameName;
1362 if ( uargs.frameName == "_top" )
1365 while ( part->parentPart() )
1366 part = part->parentPart();
1367 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1368 part->scheduleRedirection(0, url.url(), false/*don't lock history*/, userGesture);
1369 return Window::retrieve(part);
1371 if ( uargs.frameName == "_parent" )
1374 if ( part->parentPart() )
1375 part = part->parentPart();
1376 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1377 part->scheduleRedirection(0, url.url(), false/*don't lock history*/, userGesture);
1378 return Window::retrieve(part);
1380 uargs.serviceType = "text/html";
1382 // request window (new or existing if framename is set)
1383 KParts::ReadOnlyPart *newPart = 0L;
1384 emit part->browserExtension()->createNewWindow("", uargs,winargs,newPart);
1385 if (newPart && newPart->inherits("KHTMLPart")) {
1386 KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
1387 //qDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window);
1388 khtmlpart->setOpener(part);
1389 khtmlpart->setOpenedByJS(true);
1390 if (khtmlpart->document().isNull()) {
1392 khtmlpart->write("<HTML><BODY>");
1395 if (part->xmlDocImpl()) {
1396 kdDebug(6070) << "Setting domain to " << part->xmlDocImpl()->domain().string() << endl;
1397 khtmlpart->xmlDocImpl()->setDomain( part->docImpl()->domain(), true );
1400 if ( part->docImpl() )
1401 khtmlpart->docImpl()->setBaseURL( part->docImpl()->baseURL() );
1404 if (!url.isEmpty()) {
1405 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
1406 // FIXME: Need to pass referrer here.
1407 khtmlpart->scheduleRedirection(0, url.url(), false, userGesture);
1410 uargs.serviceType = QString::null;
1411 if (uargs.frameName == "_blank")
1412 uargs.frameName = QString::null;
1414 // FIXME: need to pass referrer here
1415 emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
1417 return Window::retrieve(khtmlpart); // global object
1427 case Window::ScrollBy:
1428 window->updateLayout();
1429 if(args.size() >= 2 && widget)
1430 widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
1432 case Window::Scroll:
1433 case Window::ScrollTo:
1434 window->updateLayout();
1435 if(args.size() >= 2 && widget)
1436 widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
1438 case Window::MoveBy:
1439 if(args.size() >= 2 && widget)
1441 QWidget * tl = widget->topLevelWidget();
1442 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1443 QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
1444 // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1445 if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
1446 dest.x()+tl->width() <= sg.width()+sg.x() &&
1447 dest.y()+tl->height() <= sg.height()+sg.y() )
1451 case Window::MoveTo:
1452 if(args.size() >= 2 && widget)
1454 QWidget * tl = widget->topLevelWidget();
1455 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1456 QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
1457 // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1458 if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
1459 dest.x()+tl->width() <= sg.width()+sg.x() &&
1460 dest.y()+tl->height() <= sg.height()+sg.y() )
1464 case Window::ResizeBy:
1465 if(args.size() >= 2 && widget)
1467 QWidget * tl = widget->topLevelWidget();
1468 QSize dest = tl->size() + QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1469 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1470 // Security check: within desktop limits and bigger than 100x100 (per spec)
1471 if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1472 tl->y()+dest.height() <= sg.y()+sg.height() &&
1473 dest.width() >= 100 && dest.height() >= 100 )
1475 // Take into account the window frame
1476 int deltaWidth = tl->frameGeometry().width() - tl->width();
1477 int deltaHeight = tl->frameGeometry().height() - tl->height();
1478 tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1482 case Window::ResizeTo:
1483 if(args.size() >= 2 && widget)
1485 QWidget * tl = widget->topLevelWidget();
1486 QSize dest = QSize( args[0].toInt32(exec), args[1].toInt32(exec) );
1487 QRect sg = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(tl));
1488 // Security check: within desktop limits and bigger than 100x100 (per spec)
1489 if ( tl->x()+dest.width() <= sg.x()+sg.width() &&
1490 tl->y()+dest.height() <= sg.y()+sg.height() &&
1491 dest.width() >= 100 && dest.height() >= 100 )
1493 // Take into account the window frame
1494 int deltaWidth = tl->frameGeometry().width() - tl->width();
1495 int deltaHeight = tl->frameGeometry().height() - tl->height();
1496 tl->resize( dest.width() - deltaWidth, dest.height() - deltaHeight );
1500 case Window::SetTimeout:
1501 if (!window->isSafeScript(exec))
1503 if (args.size() >= 2 && v.isA(StringType)) {
1504 int i = args[1].toInt32(exec);
1505 int r = (const_cast<Window*>(window))->installTimeout(s, i, true /*single shot*/);
1508 else if (args.size() >= 2 && v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
1509 Value func = args[0];
1510 int i = args[1].toInt32(exec);
1512 // All arguments after the second should go to the function
1513 // FIXME: could be more efficient
1514 List funcArgs = args.copyTail().copyTail();
1516 int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, true /*single shot*/);
1521 case Window::SetInterval:
1522 if (!window->isSafeScript(exec))
1524 if (args.size() >= 2 && v.isA(StringType)) {
1525 int i = args[1].toInt32(exec);
1526 int r = (const_cast<Window*>(window))->installTimeout(s, i, false);
1529 else if (args.size() >= 2 && !Object::dynamicCast(v).isNull() &&
1530 Object::dynamicCast(v).implementsCall()) {
1531 Value func = args[0];
1532 int i = args[1].toInt32(exec);
1534 // All arguments after the second should go to the function
1535 // FIXME: could be more efficient
1536 List funcArgs = args.copyTail().copyTail();
1538 int r = (const_cast<Window*>(window))->installTimeout(func, funcArgs, i, false);
1543 case Window::ClearTimeout:
1544 case Window::ClearInterval:
1545 if (!window->isSafeScript(exec))
1547 (const_cast<Window*>(window))->clearTimeout(v.toInt32(exec));
1551 widget->setActiveWindow();
1553 case Window::GetSelection:
1554 if (!window->isSafeScript(exec))
1556 return Value(window->selection());
1559 KWQ(part)->unfocusWindow();
1565 /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
1566 The close method closes only windows opened by JavaScript using the open method.
1567 If you attempt to close any other window, a confirm is generated, which
1568 lets the user choose whether the window closes.
1569 This is a security feature to prevent "mail bombs" containing self.close().
1570 However, if the window has only one document (the current one) in its
1571 session history, the close is allowed without any confirm. This is a
1572 special case for one-off windows that need to open other windows and
1573 then dispose of themselves.
1575 if (!part->openedByJS())
1577 // To conform to the SPEC, we only ask if the window
1578 // has more than one entry in the history (NS does that too).
1579 History history(exec,part);
1580 if ( history.get( exec, lengthPropertyName ).toInt32(exec) <= 1
1582 // FIXME: How are we going to handle this?
1584 || KMessageBox::questionYesNo( window->part()->view(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes
1587 (const_cast<Window*>(window))->scheduleClose();
1591 (const_cast<Window*>(window))->scheduleClose();
1594 case Window::CaptureEvents:
1595 case Window::ReleaseEvents:
1596 // If anyone implements these, they need the safescript security check.
1597 if (!window->isSafeScript(exec))
1600 // Do nothing for now. These are NS-specific legacy calls.
1602 case Window::AddEventListener: {
1603 if (!window->isSafeScript(exec))
1606 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1608 DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1609 docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1613 case Window::RemoveEventListener: {
1614 if (!window->isSafeScript(exec))
1616 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
1618 DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
1619 docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
1628 void Window::updateLayout() const
1630 DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(m_part->document().handle());
1632 docimpl->updateLayout();
1637 ////////////////////// ScheduledAction ////////////////////////
1639 ScheduledAction::ScheduledAction(Object _func, List _args, bool _singleShot)
1641 //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
1645 singleShot = _singleShot;
1648 ScheduledAction::ScheduledAction(const QString &_code, bool _singleShot)
1650 //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
1655 singleShot = _singleShot;
1658 void ScheduledAction::execute(Window *window)
1660 ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(KJSProxy::proxy(window->m_part)->interpreter());
1662 interpreter->setProcessingTimerCallback(true);
1664 //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
1666 if (func.implementsCall()) {
1668 Q_ASSERT( window->m_part );
1669 if ( window->m_part )
1671 KJS::Interpreter *interpreter = KJSProxy::proxy( window->m_part )->interpreter();
1672 ExecState *exec = interpreter->globalExec();
1673 Q_ASSERT( window == interpreter->globalObject().imp() );
1674 Object obj( window );
1675 Interpreter::lock();
1676 func.call(exec,obj,args); // note that call() creates its own execution state for the func call
1677 Interpreter::unlock();
1678 if ( exec->hadException() ) {
1680 Interpreter::lock();
1681 char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
1682 int lineNumber = exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
1683 Interpreter::unlock();
1684 if (Interpreter::shouldPrintExceptions()) {
1685 printf("(timer):%s\n", message);
1687 KWQ(window->m_part)->addMessageToConsole(message, lineNumber, QString());
1689 exec->clearException();
1695 window->m_part->executeScript(code);
1698 // Update our document's rendering following the execution of the timeout callback.
1699 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(window->m_part->document().handle());
1700 doc->updateRendering();
1702 interpreter->setProcessingTimerCallback(false);
1705 ScheduledAction::~ScheduledAction()
1707 //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
1710 ////////////////////// WindowQObject ////////////////////////
1712 WindowQObject::WindowQObject(Window *w)
1715 //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
1716 part = parent->m_part;
1717 connect( parent->m_part, SIGNAL( destroyed() ),
1718 this, SLOT( parentDestroyed() ) );
1721 WindowQObject::~WindowQObject()
1723 //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
1724 parentDestroyed(); // reuse same code
1727 void WindowQObject::parentDestroyed()
1729 //kdDebug(6070) << "WindowQObject::parentDestroyed " << this << " we have " << scheduledActions.count() << " actions in the map" << endl;
1731 QMapIterator<int,ScheduledAction*> it;
1732 for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1733 ScheduledAction *action = *it;
1734 //kdDebug(6070) << "WindowQObject::parentDestroyed deleting action " << action << endl;
1737 scheduledActions.clear();
1740 int WindowQObject::installTimeout(const UString &handler, int t, bool singleShot)
1742 //kdDebug(6070) << "WindowQObject::installTimeout " << this << " " << handler.ascii() << endl;
1743 int id = startTimer(t);
1744 ScheduledAction *action = new ScheduledAction(handler.qstring(),singleShot);
1745 scheduledActions.insert(id, action);
1746 //kdDebug(6070) << this << " got id=" << id << " action=" << action << " - now having " << scheduledActions.count() << " actions"<<endl;
1750 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
1752 Object objFunc = Object::dynamicCast( func );
1753 int id = startTimer(t);
1754 scheduledActions.insert(id, new ScheduledAction(objFunc,args,singleShot));
1758 QMap<int, ScheduledAction*> *WindowQObject::pauseTimeouts(const void *key)
1760 QMapIterator<int,ScheduledAction*> it;
1762 QMap<int, KJS::ScheduledAction*>*pausedActions = new QMap<int, KJS::ScheduledAction*>;
1763 for (it = scheduledActions.begin(); it != scheduledActions.end(); ++it) {
1764 int timerId = it.key();
1765 pauseTimer (timerId, key);
1766 pausedActions->insert(timerId, it.data());
1768 scheduledActions.clear();
1769 return pausedActions;
1772 void WindowQObject::resumeTimeouts(QMap<int, ScheduledAction*> *sa, const void *key)
1774 QMapIterator<int,ScheduledAction*> it;
1775 for (it = sa->begin(); it != sa->end(); ++it) {
1776 int timerId = it.key();
1777 scheduledActions.insert(timerId, it.data());
1780 resumeTimers (key, this);
1783 void WindowQObject::clearTimeout(int timerId, bool delAction)
1785 //kdDebug(6070) << "WindowQObject::clearTimeout " << this << " timerId=" << timerId << " delAction=" << delAction << endl;
1788 QMapIterator<int,ScheduledAction*> it = scheduledActions.find(timerId);
1789 if (it != scheduledActions.end()) {
1790 ScheduledAction *action = *it;
1791 scheduledActions.remove(it);
1797 void WindowQObject::timerEvent(QTimerEvent *e)
1799 QMapIterator<int,ScheduledAction*> it = scheduledActions.find(e->timerId());
1800 if (it != scheduledActions.end()) {
1801 ScheduledAction *action = *it;
1802 bool singleShot = action->singleShot;
1803 //kdDebug(6070) << "WindowQObject::timerEvent " << this << " action=" << action << " singleShot:" << singleShot << endl;
1805 // remove single shots installed by setTimeout()
1808 clearTimeout(e->timerId(),false);
1809 scheduledActions.remove(it);
1812 if (!parent->part().isNull())
1813 action->execute(parent);
1815 // It is important to test singleShot and not action->singleShot here - the
1816 // action could have been deleted already if not single shot and if the
1817 // JS code called by execute() calls clearTimeout().
1821 kdWarning(6070) << "WindowQObject::timerEvent this=" << this << " timer " << e->timerId()
1822 << " not found (" << scheduledActions.count() << " actions in map)" << endl;
1825 void WindowQObject::timeoutClose()
1827 if (!parent->part().isNull())
1829 //kdDebug(6070) << "WindowQObject::timeoutClose -> closing window" << endl;
1830 delete parent->m_part;
1835 bool WindowQObject::hasTimeouts()
1837 return scheduledActions.count();
1841 Value FrameArray::get(ExecState *exec, const Identifier &p) const
1844 kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
1849 QPtrList<KParts::ReadOnlyPart> frames = part->frames();
1850 unsigned int len = frames.count();
1851 if (p == lengthPropertyName)
1853 else if (p== "location") // non-standard property, but works in NS and IE
1855 Object obj = Object::dynamicCast( Window::retrieve( part ) );
1856 if ( !obj.isNull() )
1857 return obj.get( exec, "location" );
1861 // check for the name or number
1862 KParts::ReadOnlyPart *frame = part->findFrame(p.qstring());
1865 unsigned int i = p.toArrayIndex(&ok);
1867 frame = frames.at(i);
1870 // we are potentially fetching a reference to a another Window object here.
1871 // i.e. we may be accessing objects from another interpreter instance.
1872 // Therefore we have to be a bit careful with memory managment.
1873 if (frame && frame->inherits("KHTMLPart")) {
1874 KHTMLPart *khtml = static_cast<KHTMLPart*>(frame);
1875 return Window::retrieve(khtml);
1878 return ObjectImp::get(exec, p);
1881 UString FrameArray::toString(ExecState *) const
1883 return "[object FrameArray]";
1886 ////////////////////// Location Object ////////////////////////
1888 const ClassInfo Location::info = { "Location", 0, 0, 0 };
1890 @begin LocationTable 11
1891 hash Location::Hash DontDelete
1892 host Location::Host DontDelete
1893 hostname Location::Hostname DontDelete
1894 href Location::Href DontDelete
1895 pathname Location::Pathname DontDelete
1896 port Location::Port DontDelete
1897 protocol Location::Protocol DontDelete
1898 search Location::Search DontDelete
1899 [[==]] Location::EqualEqual DontDelete|ReadOnly
1900 toString Location::ToString DontDelete|Function 0
1901 replace Location::Replace DontDelete|Function 1
1902 reload Location::Reload DontDelete|Function 0
1905 IMPLEMENT_PROTOFUNC(LocationFunc)
1906 Location::Location(KHTMLPart *p) : m_part(p)
1908 //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
1911 Location::~Location()
1913 //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
1916 Value Location::get(ExecState *exec, const Identifier &p) const
1919 kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
1922 if (m_part.isNull())
1925 const Window* window = Window::retrieveWindow(m_part);
1926 if (!window || !window->isSafeScript(exec))
1929 KURL url = m_part->url();
1930 const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
1932 switch (entry->value) {
1934 return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
1936 UString str = url.host();
1938 str += ":" + QString::number((int)url.port());
1940 // Note: this is the IE spec. The NS spec swaps the two, it says
1941 // "The hostname property is the concatenation of the host and port properties, separated by a colon."
1945 return String( url.host() );
1948 return String( url.prettyURL()+"/" );
1950 return String( url.prettyURL() );
1952 return String( url.path().isEmpty() ? QString("/") : url.path() );
1954 return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
1956 return String( url.protocol()+":" );
1958 return String( url.query() );
1959 case EqualEqual: // [[==]]
1960 return String(toString(exec));
1962 return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
1964 // Look for overrides
1965 ValueImp * val = ObjectImp::getDirect(p);
1969 switch (entry->value) {
1971 return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
1973 return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
1979 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
1982 kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl;
1984 if (m_part.isNull())
1987 QString str = v.toString(exec).qstring();
1988 KURL url = m_part->url();
1989 const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
1991 switch (entry->value) {
1993 KHTMLPart* p = Window::retrieveActive(exec)->part();
1995 url = p->htmlDocument().completeURL( str ).string();
2004 QString host = str.left(str.find(":"));
2005 QString port = str.mid(str.find(":")+1);
2007 url.setPort(port.toUInt());
2017 url.setPort(str.toUInt());
2020 url.setProtocol(str);
2027 ObjectImp::put(exec, p, v, attr);
2030 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2032 // We want a new history item if this JS was called via a user gesture
2033 m_part->scheduleRedirection(0, url.url(), !userGesture, userGesture);
2035 m_part->scheduleRedirection(0, url.url(), false /*don't lock history*/, userGesture);
2039 Value Location::toPrimitive(ExecState *exec, Type) const
2041 return String(toString(exec));
2044 UString Location::toString(ExecState *) const
2046 if (!m_part->url().hasPath())
2047 return m_part->url().prettyURL()+"/";
2049 return m_part->url().prettyURL();
2052 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2054 if (!thisObj.inherits(&Location::info)) {
2055 Object err = Error::create(exec,TypeError);
2056 exec->setException(err);
2059 Location *location = static_cast<Location *>(thisObj.imp());
2060 KHTMLPart *part = location->part();
2063 Window* window = Window::retrieveWindow(part);
2064 if (!window->isSafeScript(exec) && id != Location::Replace)
2068 case Location::Replace:
2070 QString str = args[0].toString(exec).qstring();
2071 KHTMLPart* p = Window::retrieveActive(exec)->part();
2073 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2074 part->scheduleRedirection(0, p->htmlDocument().completeURL(str).string(), true /*lock history*/, userGesture);
2078 case Location::Reload:
2080 bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
2081 part->scheduleRedirection(0, part->url().url(), true/*lock history*/, userGesture);
2084 case Location::ToString:
2085 return String(location->toString(exec));
2088 kdDebug(6070) << "LocationFunc::tryExecute - no part!" << endl;
2092 ////////////////////// Selection Object ////////////////////////
2094 const ClassInfo Selection::info = { "Selection", 0, 0, 0 };
2096 @begin SelectionTable 19
2097 anchorNode Selection::AnchorNode DontDelete|ReadOnly
2098 anchorOffset Selection::AnchorOffset DontDelete|ReadOnly
2099 focusNode Selection::FocusNode DontDelete|ReadOnly
2100 focusOffset Selection::FocusOffset DontDelete|ReadOnly
2101 baseNode Selection::AnchorNode DontDelete|ReadOnly
2102 baseOffset Selection::AnchorOffset DontDelete|ReadOnly
2103 extentNode Selection::FocusNode DontDelete|ReadOnly
2104 extentOffset Selection::FocusOffset DontDelete|ReadOnly
2105 isCollapsed Selection::IsCollapsed DontDelete|ReadOnly
2106 type Selection::_Type DontDelete|ReadOnly
2107 [[==]] Selection::EqualEqual DontDelete|ReadOnly
2108 toString Selection::ToString DontDelete|Function 0
2109 collapse Selection::Collapse DontDelete|Function 2
2110 collapseToEnd Selection::CollapseToEnd DontDelete|Function 0
2111 collapseToStart Selection::CollapseToStart DontDelete|Function 0
2112 empty Selection::Empty DontDelete|Function 0
2113 setBaseAndExtent Selection::SetBaseAndExtent DontDelete|Function 4
2114 setPosition Selection::SetPosition DontDelete|Function 2
2115 modify Selection::Modify DontDelete|Function 3
2118 IMPLEMENT_PROTOFUNC(SelectionFunc)
2119 Selection::Selection(KHTMLPart *p) : m_part(p)
2121 //kdDebug(6070) << "Selection::Selection " << this << " m_part=" << (void*)m_part << endl;
2124 Selection::~Selection()
2126 //kdDebug(6070) << "Selection::~Selection " << this << " m_part=" << (void*)m_part << endl;
2129 Value Selection::get(ExecState *exec, const Identifier &p) const
2132 kdDebug(6070) << "Selection::get " << p.qstring() << " m_part=" << (void*)m_part << endl;
2135 if (m_part.isNull())
2138 const Window* window = Window::retrieveWindow(m_part);
2139 if (!window || !window->isSafeScript(exec))
2142 DocumentImpl *docimpl = m_part->xmlDocImpl();
2144 docimpl->updateLayout();
2146 KURL url = m_part->url();
2147 const HashEntry *entry = Lookup::findEntry(&SelectionTable, p);
2149 switch (entry->value) {
2152 return getDOMNode(exec, Node(m_part->selection().base().node()));
2155 return Number(m_part->selection().base().offset());
2158 return getDOMNode(exec, Node(m_part->selection().extent().node()));
2161 return Number(m_part->selection().extent().offset());
2163 return Boolean(m_part->selection().state() == DOM::Selection::CARET);
2165 switch (m_part->selection().state()) {
2166 case DOM::Selection::NONE:
2167 return String("None");
2168 case DOM::Selection::CARET:
2169 return String("Caret");
2170 case DOM::Selection::RANGE:
2171 return String("Range");
2175 return String(toString(exec));
2177 return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2179 // Look for overrides
2180 ValueImp * val = ObjectImp::getDirect(p);
2184 switch (entry->value) {
2187 case CollapseToStart:
2189 case SetBaseAndExtent:
2192 return lookupOrCreateFunction<SelectionFunc>(exec,p,this,entry->value,entry->params,entry->attr);
2198 void Selection::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
2202 Value Selection::toPrimitive(ExecState *exec, Type) const
2204 return String(toString(exec));
2207 UString Selection::toString(ExecState *) const
2209 if (m_part->selection().state() != DOM::Selection::RANGE)
2211 return UString(m_part->selection().toRange().toString());
2214 Value SelectionFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2216 if (!thisObj.inherits(&Selection::info)) {
2217 Object err = Error::create(exec,TypeError);
2218 exec->setException(err);
2221 Selection *selection = static_cast<Selection *>(thisObj.imp());
2222 KHTMLPart *part = selection->part();
2224 DocumentImpl *docimpl = part->xmlDocImpl();
2226 docimpl->updateLayout();
2229 case Selection::Collapse:
2230 TypingCommand::closeTyping(part->lastEditCommand());
2231 part->setSelection(DOM::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec))));
2233 case Selection::CollapseToEnd:
2234 TypingCommand::closeTyping(part->lastEditCommand());
2235 part->setSelection(DOM::Selection(part->selection().end()));
2237 case Selection::CollapseToStart:
2238 TypingCommand::closeTyping(part->lastEditCommand());
2239 part->setSelection(DOM::Selection(part->selection().start()));
2241 case Selection::Empty:
2242 TypingCommand::closeTyping(part->lastEditCommand());
2243 part->clearSelection();
2245 case Selection::SetBaseAndExtent: {
2246 TypingCommand::closeTyping(part->lastEditCommand());
2247 Position base(KJS::toNode(args[0]).handle(), args[1].toInt32(exec));
2248 Position extent(KJS::toNode(args[2]).handle(), args[3].toInt32(exec));
2249 part->setSelection(DOM::Selection(base, extent));
2252 case Selection::SetPosition:
2253 TypingCommand::closeTyping(part->lastEditCommand());
2254 part->setSelection(DOM::Selection(Position(KJS::toNode(args[0]).handle(), args[1].toInt32(exec))));
2256 case Selection::Modify: {
2257 TypingCommand::closeTyping(part->lastEditCommand());
2258 DOM::Selection s(part->selection());
2259 DOM::Selection::EAlter alter = DOM::Selection::MOVE;
2260 if (args[0].toString(exec).string().lower() == "extend")
2261 alter = DOM::Selection::EXTEND;
2262 DOMString directionString = args[1].toString(exec).string().lower();
2263 DOM::Selection::EDirection direction = DOM::Selection::FORWARD;
2264 if (directionString == "backward")
2265 direction = DOM::Selection::BACKWARD;
2266 else if (directionString == "left")
2267 direction = DOM::Selection::LEFT;
2268 if (directionString == "right")
2269 direction = DOM::Selection::RIGHT;
2270 DOM::Selection::ETextGranularity granularity = DOM::Selection::CHARACTER;
2271 DOMString granularityString = args[2].toString(exec).string().lower();
2272 if (granularityString == "word")
2273 granularity = DOM::Selection::WORD;
2274 else if (granularityString == "line")
2275 granularity = DOM::Selection::LINE;
2276 s.modify(alter, direction, granularity);
2277 part->setSelection(s);
2285 ////////////////////// History Object ////////////////////////
2287 const ClassInfo History::info = { "History", 0, 0, 0 };
2289 @begin HistoryTable 4
2290 length History::Length DontDelete|ReadOnly
2291 back History::Back DontDelete|Function 0
2292 forward History::Forward DontDelete|Function 0
2293 go History::Go DontDelete|Function 1
2296 IMPLEMENT_PROTOFUNC(HistoryFunc)
2298 Value History::get(ExecState *exec, const Identifier &p) const
2300 return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
2303 Value History::getValueProperty(ExecState *, int token) const
2308 KParts::BrowserExtension *ext = part->browserExtension();
2312 KParts::BrowserInterface *iface = ext->browserInterface();
2316 QVariant length = iface->property( "historyLength" );
2318 if ( length.type() != QVariant::UInt )
2321 return Number( length.toUInt() );
2324 kdWarning() << "Unhandled token in History::getValueProperty : " << token << endl;
2329 UString History::toString(ExecState *exec) const
2331 return "[object History]";
2334 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
2336 if (!thisObj.inherits(&History::info)) {
2337 Object err = Error::create(exec,TypeError);
2338 exec->setException(err);
2341 History *history = static_cast<History *>(thisObj.imp());
2348 case History::Forward:
2352 steps = args[0].toInt32(exec);
2358 history->part->scheduleHistoryNavigation(steps);
2362 /////////////////////////////////////////////////////////////////////////////
2366 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
2368 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
2370 if ( p.qstring().startsWith( "goHistory" ) ) return false;
2375 Value Konqueror::get(ExecState *exec, const Identifier &p) const
2377 if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
2380 KParts::BrowserExtension *ext = part->browserExtension();
2382 KParts::BrowserInterface *iface = ext->browserInterface();
2384 QVariant prop = iface->property( p.qstring().latin1() );
2386 if ( prop.isValid() ) {
2387 switch( prop.type() ) {
2389 return Number( prop.toInt() );
2390 case QVariant::String:
2391 return String( prop.toString() );
2399 return /*Function*/( new KonquerorFunc(this, p.qstring().latin1() ) );
2402 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
2404 KParts::BrowserExtension *ext = konqueror->part->browserExtension();
2409 KParts::BrowserInterface *iface = ext->browserInterface();
2414 QCString n = m_name.data();
2416 iface->callMethod( n.data(), QVariant() );
2421 UString Konqueror::toString(ExecState *) const
2423 return UString("[object Konqueror]");
2427 /////////////////////////////////////////////////////////////////////////////
2429 #include "kjs_window.moc"