fix logic
[personal-kdelibs.git] / khtml / ecma / kjs_window.cpp
blob1ca7c20c22708c8130b9a9bfbb09d9868dc6348f
1 // -*- c-basic-offset: 2 -*-
2 /*
3 * This file is part of the KDE libraries
4 * Copyright (C) 2000-2003 Harri Porten (porten@kde.org)
5 * Copyright (C) 2001-2003 David Faure (faure@kde.org)
6 * Copyright (C) 2003 Apple Computer, Inc.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "kjs_window.h"
25 #include <khtmlview.h>
26 #include <khtml_part.h>
27 #include <khtmlpart_p.h>
28 #include <khtml_settings.h>
29 #include <xml/dom2_eventsimpl.h>
30 #include <xml/dom_docimpl.h>
31 #include <dom/html_document.h>
32 #include <misc/htmltags.h>
33 #include <html/html_documentimpl.h>
34 #include <rendering/render_frames.h>
36 #include <config.h>
38 #include <QtCore/QTimer>
39 #include <QtGui/QApplication>
40 #include <kdebug.h>
41 #include <kmessagebox.h>
42 #include <kinputdialog.h>
43 #include <klocale.h>
44 #include <kcodecs.h>
45 #include <kparts/browserinterface.h>
46 #include <kwindowsystem.h>
48 #ifndef KONQ_EMBEDDED
49 #include <kbookmarkmanager.h>
50 #include <kbookmarkdialog.h>
51 #endif
52 #include <kglobalsettings.h>
53 #include <assert.h>
54 #include <QtGui/QStyle>
55 #include <QtCore/QObject>
56 #include <QtGui/QTextDocument>
57 #include <kstringhandler.h>
59 #include "kjs_proxy.h"
60 #include "kjs_navigator.h"
61 #include "kjs_mozilla.h"
62 #include "kjs_html.h"
63 #include "kjs_range.h"
64 #include "kjs_traversal.h"
65 #include "kjs_css.h"
66 #include "kjs_events.h"
67 #include "kjs_views.h"
68 #include "kjs_audio.h"
69 #include "kjs_context2d.h"
70 #include "xmlhttprequest.h"
71 #include "xmlserializer.h"
72 #include "domparser.h"
74 #include <rendering/render_replaced.h>
77 using namespace KJS;
78 using namespace DOM;
80 namespace KJS {
82 class History : public JSObject {
83 friend class HistoryFunc;
84 public:
85 History(ExecState *exec, KHTMLPart *p)
86 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
87 virtual bool getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot);
88 JSValue *getValueProperty(ExecState *exec, int token) const;
89 virtual const ClassInfo* classInfo() const { return &info; }
90 static const ClassInfo info;
91 enum { Back, Forward, Go, Length };
92 private:
93 QPointer<KHTMLPart> part;
96 class External : public JSObject {
97 friend class ExternalFunc;
98 public:
99 External(ExecState *exec, KHTMLPart *p)
100 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { }
101 virtual bool getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot);
102 virtual const ClassInfo* classInfo() const { return &info; }
103 static const ClassInfo info;
104 enum { AddFavorite };
105 private:
106 QPointer<KHTMLPart> part;
108 } //namespace KJS
110 #include "kjs_window.lut.h"
112 namespace KJS {
114 ////////////////////// Screen Object ////////////////////////
116 // table for screen object
118 @begin ScreenTable 7
119 height Screen::Height DontEnum|ReadOnly
120 width Screen::Width DontEnum|ReadOnly
121 colorDepth Screen::ColorDepth DontEnum|ReadOnly
122 pixelDepth Screen::PixelDepth DontEnum|ReadOnly
123 availLeft Screen::AvailLeft DontEnum|ReadOnly
124 availTop Screen::AvailTop DontEnum|ReadOnly
125 availHeight Screen::AvailHeight DontEnum|ReadOnly
126 availWidth Screen::AvailWidth DontEnum|ReadOnly
127 @end
130 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
132 // We set the object prototype so that toString is implemented
133 Screen::Screen(ExecState *exec)
134 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) {}
136 bool Screen::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
138 #ifdef KJS_VERBOSE
139 kDebug(6070) << "Screen::getPropertyName " << propertyName.qstring();
140 #endif
141 return getStaticValueSlot<Screen, JSObject>(exec, &ScreenTable, this, propertyName, slot);
144 JSValue *Screen::getValueProperty(ExecState *exec, int token) const
146 QWidget *thisWidget = Window::retrieveActive(exec)->part()->widget();
147 QRect sg = KGlobalSettings::desktopGeometry(thisWidget);
149 switch( token ) {
150 case Height:
151 return jsNumber(sg.height());
152 case Width:
153 return jsNumber(sg.width());
154 case ColorDepth:
155 case PixelDepth:
156 return jsNumber(thisWidget->depth());
157 case AvailLeft: {
158 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
159 QRect clipped = KWindowSystem::workArea().intersect(sg);
160 return jsNumber(clipped.x()-sg.x());
161 #else
162 return jsNumber(10);
163 #endif
165 case AvailTop: {
166 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
167 QRect clipped = KWindowSystem::workArea().intersect(sg);
168 return jsNumber(clipped.y()-sg.y());
169 #else
170 return jsNumber(10);
171 #endif
173 case AvailHeight: {
174 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
175 QRect clipped = KWindowSystem::workArea().intersect(sg);
176 return jsNumber(clipped.height());
177 #else
178 return jsNumber(100);
179 #endif
181 case AvailWidth: {
182 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
183 QRect clipped = KWindowSystem::workArea().intersect(sg);
184 return jsNumber(clipped.width());
185 #else
186 return jsNumber(100);
187 #endif
189 default:
190 kDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token;
191 return jsUndefined();
195 ////////////////////// Window Object ////////////////////////
197 const ClassInfo Window::info = { "Window", &DOMAbstractView::info, &WindowTable, 0 };
200 @begin WindowTable 233
201 atob Window::AToB DontDelete|Function 1
202 btoa Window::BToA DontDelete|Function 1
203 closed Window::Closed DontDelete|ReadOnly
204 crypto Window::Crypto DontDelete|ReadOnly
205 defaultStatus Window::DefaultStatus DontDelete
206 defaultstatus Window::DefaultStatus DontDelete
207 status Window::Status DontDelete
208 document Window::Document DontDelete|ReadOnly
209 frameElement Window::FrameElement DontDelete|ReadOnly
210 frames Window::Frames DontDelete
211 history Window::_History DontDelete|ReadOnly
212 external Window::_External DontDelete|ReadOnly
213 event Window::Event DontDelete|ReadOnly
214 innerHeight Window::InnerHeight DontDelete|ReadOnly
215 innerWidth Window::InnerWidth DontDelete|ReadOnly
216 length Window::Length DontDelete
217 location Window::_Location DontDelete
218 name Window::Name DontDelete
219 navigator Window::_Navigator DontDelete|ReadOnly
220 clientInformation Window::ClientInformation DontDelete|ReadOnly
221 konqueror Window::_Konqueror DontDelete
222 offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly
223 opener Window::Opener DontDelete|ReadOnly
224 outerHeight Window::OuterHeight DontDelete|ReadOnly
225 outerWidth Window::OuterWidth DontDelete|ReadOnly
226 pageXOffset Window::PageXOffset DontDelete|ReadOnly
227 pageYOffset Window::PageYOffset DontDelete|ReadOnly
228 parent Window::Parent DontDelete
229 personalbar Window::Personalbar DontDelete
230 screenX Window::ScreenX DontDelete|ReadOnly
231 screenY Window::ScreenY DontDelete|ReadOnly
232 scrollbars Window::Scrollbars DontDelete|ReadOnly
233 scroll Window::Scroll DontDelete|Function 2
234 scrollBy Window::ScrollBy DontDelete|Function 2
235 scrollTo Window::ScrollTo DontDelete|Function 2
236 scrollX Window::ScrollX DontDelete|ReadOnly
237 scrollY Window::ScrollY DontDelete|ReadOnly
238 moveBy Window::MoveBy DontDelete|Function 2
239 moveTo Window::MoveTo DontDelete|Function 2
240 resizeBy Window::ResizeBy DontDelete|Function 2
241 resizeTo Window::ResizeTo DontDelete|Function 2
242 self Window::Self DontDelete|ReadOnly
243 window Window::_Window DontDelete|ReadOnly
244 top Window::Top DontDelete
245 screen Window::_Screen DontDelete|ReadOnly
246 alert Window::Alert DontDelete|Function 1
247 confirm Window::Confirm DontDelete|Function 1
248 prompt Window::Prompt DontDelete|Function 2
249 open Window::Open DontDelete|Function 3
250 setTimeout Window::SetTimeout DontDelete|Function 2
251 clearTimeout Window::ClearTimeout DontDelete|Function 1
252 focus Window::Focus DontDelete|Function 0
253 blur Window::Blur DontDelete|Function 0
254 close Window::Close DontDelete|Function 0
255 setInterval Window::SetInterval DontDelete|Function 2
256 clearInterval Window::ClearInterval DontDelete|Function 1
257 captureEvents Window::CaptureEvents DontDelete|Function 0
258 releaseEvents Window::ReleaseEvents DontDelete|Function 0
259 print Window::Print DontDelete|Function 0
260 addEventListener Window::AddEventListener DontDelete|Function 3
261 removeEventListener Window::RemoveEventListener DontDelete|Function 3
262 # Normally found in prototype. Add to window object itself to make them
263 # accessible in closed and cross-site windows
264 valueOf Window::ValueOf DontEnum|DontDelete|Function 0
265 toString Window::ToString DontEnum|DontDelete|Function 0
266 # IE extension
267 navigate Window::Navigate DontDelete|Function 1
268 # Mozilla extension
269 sidebar Window::SideBar DontDelete|ReadOnly
270 getComputedStyle Window::GetComputedStyle DontDelete|Function 2
272 # Warning, when adding a function to this object you need to add a case in Window::get
274 # Event handlers
275 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
276 # ondeactivate, onhelp, onmovestart/end, onresizestart/end.
277 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
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 onmove Window::Onmove DontDelete
296 onreset Window::Onreset DontDelete
297 onresize Window::Onresize DontDelete
298 onscroll Window::Onscroll DontDelete
299 onselect Window::Onselect DontDelete
300 onsubmit Window::Onsubmit DontDelete
301 onunload Window::Onunload DontDelete
303 # Constructors/constant tables
304 Node Window::Node DontEnum|DontDelete
305 Event Window::EventCtor DontEnum|DontDelete
306 Range Window::Range DontEnum|DontDelete
307 NodeFilter Window::NodeFilter DontEnum|DontDelete
308 NodeList Window::NodeList DontEnum|DontDelete
309 DOMException Window::DOMException DontEnum|DontDelete
310 RangeException Window::RangeException DontEnum|DontDelete
311 CSSRule Window::CSSRule DontEnum|DontDelete
312 MutationEvent Window::MutationEventCtor DontEnum|DontDelete
313 KeyboardEvent Window::KeyboardEventCtor DontEnum|DontDelete
314 EventException Window::EventExceptionCtor DontEnum|DontDelete
315 Audio Window::Audio DontEnum|DontDelete
316 Image Window::Image DontEnum|DontDelete
317 Option Window::Option DontEnum|DontDelete
318 XMLHttpRequest Window::XMLHttpRequest DontEnum|DontDelete
319 XMLSerializer Window::XMLSerializer DontEnum|DontDelete
320 DOMParser Window::DOMParser DontEnum|DontDelete
322 # Mozilla dom emulation ones.
323 Element Window::ElementCtor DontEnum|DontDelete
324 Document Window::DocumentCtor DontEnum|DontDelete
325 #this one is an alias since we don't have a separate XMLDocument
326 XMLDocument Window::DocumentCtor DontEnum|DontDelete
327 HTMLElement Window::HTMLElementCtor DontEnum|DontDelete
328 HTMLDocument Window::HTMLDocumentCtor DontEnum|DontDelete
329 HTMLHtmlElement Window::HTMLHtmlElementCtor DontEnum|DontDelete
330 HTMLHeadElement Window::HTMLHeadElementCtor DontEnum|DontDelete
331 HTMLLinkElement Window::HTMLLinkElementCtor DontEnum|DontDelete
332 HTMLTitleElement Window::HTMLTitleElementCtor DontEnum|DontDelete
333 HTMLMetaElement Window::HTMLMetaElementCtor DontEnum|DontDelete
334 HTMLBaseElement Window::HTMLBaseElementCtor DontEnum|DontDelete
335 HTMLIsIndexElement Window::HTMLIsIndexElementCtor DontEnum|DontDelete
336 HTMLStyleElement Window::HTMLStyleElementCtor DontEnum|DontDelete
337 HTMLBodyElement Window::HTMLBodyElementCtor DontEnum|DontDelete
338 HTMLFormElement Window::HTMLFormElementCtor DontEnum|DontDelete
339 HTMLSelectElement Window::HTMLSelectElementCtor DontEnum|DontDelete
340 HTMLOptGroupElement Window::HTMLOptGroupElementCtor DontEnum|DontDelete
341 HTMLOptionElement Window::HTMLOptionElementCtor DontEnum|DontDelete
342 HTMLInputElement Window::HTMLInputElementCtor DontEnum|DontDelete
343 HTMLTextAreaElement Window::HTMLTextAreaElementCtor DontEnum|DontDelete
344 HTMLButtonElement Window::HTMLButtonElementCtor DontEnum|DontDelete
345 HTMLLabelElement Window::HTMLLabelElementCtor DontEnum|DontDelete
346 HTMLFieldSetElement Window::HTMLFieldSetElementCtor DontEnum|DontDelete
347 HTMLLegendElement Window::HTMLLegendElementCtor DontEnum|DontDelete
348 HTMLUListElement Window::HTMLUListElementCtor DontEnum|DontDelete
349 HTMLOListElement Window::HTMLOListElementCtor DontEnum|DontDelete
350 HTMLDListElement Window::HTMLDListElementCtor DontEnum|DontDelete
351 HTMLDirectoryElement Window::HTMLDirectoryElementCtor DontEnum|DontDelete
352 HTMLMenuElement Window::HTMLMenuElementCtor DontEnum|DontDelete
353 HTMLLIElement Window::HTMLLIElementCtor DontEnum|DontDelete
354 HTMLDivElement Window::HTMLDivElementCtor DontEnum|DontDelete
355 HTMLParagraphElement Window::HTMLParagraphElementCtor DontEnum|DontDelete
356 HTMLHeadingElement Window::HTMLHeadingElementCtor DontEnum|DontDelete
357 HTMLBlockQuoteElement Window::HTMLBlockQuoteElementCtor DontEnum|DontDelete
358 HTMLQuoteElement Window::HTMLQuoteElementCtor DontEnum|DontDelete
359 HTMLPreElement Window::HTMLPreElementCtor DontEnum|DontDelete
360 HTMLBRElement Window::HTMLBRElementCtor DontEnum|DontDelete
361 HTMLBaseFontElement Window::HTMLBaseFontElementCtor DontEnum|DontDelete
362 HTMLFontElement Window::HTMLFontElementCtor DontEnum|DontDelete
363 HTMLHRElement Window::HTMLHRElementCtor DontEnum|DontDelete
364 HTMLModElement Window::HTMLModElementCtor DontEnum|DontDelete
365 HTMLAnchorElement Window::HTMLAnchorElementCtor DontEnum|DontDelete
366 HTMLImageElement Window::HTMLImageElementCtor DontEnum|DontDelete
367 HTMLObjectElement Window::HTMLObjectElementCtor DontEnum|DontDelete
368 HTMLParamElement Window::HTMLParamElementCtor DontEnum|DontDelete
369 HTMLAppletElement Window::HTMLAppletElementCtor DontEnum|DontDelete
370 HTMLMapElement Window::HTMLMapElementCtor DontEnum|DontDelete
371 HTMLAreaElement Window::HTMLAreaElementCtor DontEnum|DontDelete
372 HTMLScriptElement Window::HTMLScriptElementCtor DontEnum|DontDelete
373 HTMLTableElement Window::HTMLTableElementCtor DontEnum|DontDelete
374 HTMLTableCaptionElement Window::HTMLTableCaptionElementCtor DontEnum|DontDelete
375 HTMLTableColElement Window::HTMLTableColElementCtor DontEnum|DontDelete
376 HTMLTableSectionElement Window::HTMLTableSectionElementCtor DontEnum|DontDelete
377 HTMLTableRowElement Window::HTMLTableRowElementCtor DontEnum|DontDelete
378 HTMLTableCellElement Window::HTMLTableCellElementCtor DontEnum|DontDelete
379 HTMLFrameSetElement Window::HTMLFrameSetElementCtor DontEnum|DontDelete
380 HTMLLayerElement Window::HTMLLayerElementCtor DontEnum|DontDelete
381 HTMLFrameElement Window::HTMLFrameElementCtor DontEnum|DontDelete
382 HTMLIFrameElement Window::HTMLIFrameElementCtor DontEnum|DontDelete
383 HTMLCollection Window::HTMLCollectionCtor DontEnum|DontDelete
384 HTMLCanvasElement Window::HTMLCanvasElementCtor DontEnum|DontDelete
385 CSSStyleDeclaration Window::CSSStyleDeclarationCtor DontEnum|DontDelete
386 CanvasRenderingContext2D Window::Context2DCtor DontEnum|DontDelete
387 @end
389 KJS_IMPLEMENT_PROTOFUNC(WindowFunc)
391 Window::Window(khtml::ChildFrame *p)
392 : JSGlobalObject(/*no proto*/), m_frame(p), screen(0), history(0), external(0), loc(0), m_evt(0)
394 winq = new WindowQObject(this);
395 //kDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name();
398 Window::~Window()
400 delete winq;
403 Window *Window::retrieveWindow(KParts::ReadOnlyPart *p)
405 JSObject *obj = retrieve( p )->getObject();
406 #ifndef NDEBUG
407 // obj should never be null, except when javascript has been disabled in that part.
408 KHTMLPart *part = qobject_cast<KHTMLPart*>(p);
409 if ( part && part->jScriptEnabled() )
411 assert( obj );
412 #ifndef QWS
413 assert( dynamic_cast<KJS::Window*>(obj) ); // type checking
414 #endif
416 #endif
417 if ( !obj ) // JS disabled
418 return 0;
419 return static_cast<KJS::Window*>(obj);
422 Window *Window::retrieveActive(ExecState *exec)
424 JSValue *imp = exec->dynamicInterpreter()->globalObject();
425 assert( imp );
426 #ifndef QWS
427 assert( dynamic_cast<KJS::Window*>(imp) );
428 #endif
429 return static_cast<KJS::Window*>(imp);
432 JSValue *Window::retrieve(KParts::ReadOnlyPart *p)
434 assert(p);
435 KHTMLPart * part = qobject_cast<KHTMLPart*>(p);
436 KJSProxy *proxy = 0L;
437 if (!part) {
438 part = qobject_cast<KHTMLPart*>(p->parent());
439 if (part)
440 proxy = part->framejScript(p);
441 } else
442 proxy = part->jScript();
443 if (proxy) {
444 #ifdef KJS_VERBOSE
445 kDebug(6070) << "Window::retrieve part=" << part << " '" << part->objectName() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject();
446 #endif
447 return proxy->interpreter()->globalObject(); // the Global object is the "window"
448 } else {
449 #ifdef KJS_VERBOSE
450 kDebug(6070) << "Window::retrieve part=" << p << " '" << p->objectName() << "' no jsproxy.";
451 #endif
452 return jsUndefined(); // This can happen with JS disabled on the domain of that window
456 Location *Window::location() const
458 if (!loc)
459 const_cast<Window*>(this)->loc = new Location(m_frame);
460 return loc;
463 // reference our special objects during garbage collection
464 void Window::mark()
466 JSObject::mark();
467 if (screen && !screen->marked())
468 screen->mark();
469 if (history && !history->marked())
470 history->mark();
471 if (external && !external->marked())
472 external->mark();
473 //kDebug(6070) << "Window::mark " << this << " marking loc=" << loc;
474 if (loc && !loc->marked())
475 loc->mark();
476 if (winq)
477 winq->mark();
480 UString Window::toString(ExecState *) const
482 return "[object Window]";
485 bool Window::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
487 #ifdef KJS_VERBOSE
488 kDebug(6070) << "Window("<<this<<")::getOwnPropertySlot " << propertyName.qstring();
489 #endif
491 // we want only limited operations on a closed window
492 if (m_frame.isNull() || m_frame->m_part.isNull()) {
493 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
494 if (entry) {
495 switch (entry->value) {
496 case Closed:
497 case _Location:
498 case ValueOf:
499 case ToString:
500 getSlotFromEntry<WindowFunc, Window>(entry, this, slot);
501 return true;
502 default:
503 break;
506 slot.setUndefined(this);
507 return true;
510 // Look for overrides first
511 JSValue **val = getDirectLocation(propertyName);
512 if (val) {
513 if (isSafeScript(exec))
514 fillDirectLocationSlot(slot, val);
515 else
516 slot.setUndefined(this);
517 return true;
520 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
521 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
523 // properties that work on all windows
524 if (entry) {
525 // ReadOnlyPart first
527 switch(entry->value) {
528 case Closed:
529 case _Location: // No isSafeScript test here, we must be able to _set_ location.href (#49819)
530 case _Window:
531 case Self:
532 getSlotFromEntry<WindowFunc, Window>(entry, this, slot);
533 return true;
534 default:
535 break;
537 if (!part) {
538 slot.setUndefined(this);
539 return true;
542 // KHTMLPart next
543 switch(entry->value) {
544 case Frames:
545 case Opener:
546 case Parent:
547 case Top:
548 case Alert:
549 case Confirm:
550 case Prompt:
551 case Open:
552 case Close:
553 case Focus:
554 case Blur:
555 case AToB:
556 case BToA:
557 case ValueOf:
558 case ToString:
559 getSlotFromEntry<WindowFunc, Window>(entry, this, slot);
560 return true;
561 default:
562 break;
564 } else if (!part) {
565 // not a KHTMLPart
566 QString rvalue;
567 KParts::LiveConnectExtension::Type rtype;
568 unsigned long robjid;
569 if (m_frame->m_liveconnect &&
570 isSafeScript(exec) &&
571 m_frame->m_liveconnect->get(0, propertyName.qstring(), rtype, robjid, rvalue))
572 return getImmediateValueSlot(this,
573 getLiveConnectValue(m_frame->m_liveconnect, propertyName.qstring(), rtype, rvalue, robjid), slot);
575 slot.setUndefined(this);
576 return true;
579 // properties that only work on safe windows - we can handle them now..
580 if (isSafeScript(exec) && entry)
582 // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses
583 // if (navigate) to test for IE (unlikely).
584 if (entry->value == Navigate && exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat ) {
585 slot.setUndefined(this);
586 return true;
589 getSlotFromEntry<WindowFunc, Window>(entry, this, slot);
590 return true;
593 KParts::ReadOnlyPart *rop = part->findFramePart( propertyName.qstring() );
595 if (rop) {
596 slot.setCustom(this, framePartGetter);
597 return true;
600 // allow window[1] or parent[1] etc. (#56983)
601 bool ok;
602 unsigned int i = propertyName.toArrayIndex(&ok);
603 if (ok && frameByIndex(i)) {
604 slot.setCustomIndex(this, i, indexGetterAdapter<Window>);
605 return true;
608 // allow shortcuts like 'Image1' instead of document.images.Image1
609 DOM::DocumentImpl *doc = part->xmlDocImpl();
610 if (isSafeScript(exec) && doc && doc->isHTMLDocument()) {
611 DOM::ElementMappingCache::ItemInfo* info = doc ->underDocNamedCache().get(propertyName.qstring());
612 if (info || doc->getElementById(propertyName.domString())) {
613 slot.setCustom(this, namedItemGetter);
614 return true;
618 // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
619 // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
620 #ifdef KJS_VERBOSE
621 kDebug(6070) << "WARNING: Window::get property not found: " << propertyName.qstring();
622 #endif
624 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
627 KParts::ReadOnlyPart* Window::frameByIndex(unsigned i)
629 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
630 QList<KParts::ReadOnlyPart*> frames = part->frames();
631 unsigned int len = frames.count();
632 if (i < len) {
633 KParts::ReadOnlyPart* frame = frames.at(i);
634 return frame;
636 return 0;
639 JSValue* Window::indexGetter(ExecState *exec, unsigned index)
641 KParts::ReadOnlyPart* frame = frameByIndex(index);
642 if (frame)
643 return Window::retrieve(frame);
644 return jsUndefined(); //### ?
647 JSValue *Window::framePartGetter(ExecState *exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
649 Window* thisObj = static_cast<Window*>(slot.slotBase());
650 KHTMLPart *part = qobject_cast<KHTMLPart*>(thisObj->m_frame->m_part);
651 KParts::ReadOnlyPart *rop = part->findFramePart( propertyName.qstring() );
652 return thisObj->retrieve(rop);
655 JSValue *Window::namedItemGetter(ExecState *exec, JSObject*, const Identifier& p, const PropertySlot& slot)
657 Window* thisObj = static_cast<Window*>(slot.slotBase());
658 KHTMLPart *part = qobject_cast<KHTMLPart*>(thisObj->m_frame->m_part);
659 DOM::DocumentImpl* doc = part->xmlDocImpl();
661 DOM::ElementMappingCache::ItemInfo* info = doc->underDocNamedCache().get(p.qstring());
662 if (info) {
663 if (info->nd)
664 return getDOMNode(exec, info->nd);
665 else {
666 //No cached mapping, do it by hand...
667 DOM::HTMLMappedNameCollectionImpl* coll = new DOM::HTMLMappedNameCollectionImpl(doc,
668 DOM::HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, p.domString());
670 if (coll->length() == 1) {
671 info->nd = static_cast<DOM::ElementImpl*>(coll->firstItem());
672 delete coll;
673 return getDOMNode(exec, info->nd);
675 return getHTMLCollection(exec, coll);
679 DOM::ElementImpl* element = doc->getElementById(p.domString());
680 return getDOMNode(exec, element);
683 JSValue* Window::getValueProperty(ExecState *exec, int token)
685 KHTMLPart *part = m_frame.isNull() ? 0 : qobject_cast<KHTMLPart*>(m_frame->m_part);
686 if (!part) {
687 switch (token) {
688 case Closed:
689 return jsBoolean(true);
690 case _Location:
691 return jsNull();
692 default:
693 return jsUndefined();
697 switch(token) {
698 case Closed:
699 return jsBoolean(!part);
700 case _Location:
701 // No isSafeScript test here, we must be able to _set_ location.href (#49819)
702 return location();
703 case _Window:
704 case Self:
705 return retrieve(part);
706 case Frames:
707 return this;
708 case Opener:
709 if (!part->opener())
710 return jsNull(); // ### a null Window might be better, but == null
711 else // doesn't work yet
712 return retrieve(part->opener());
713 case Parent:
714 return retrieve(part && part->parentPart() ? part->parentPart() : (KHTMLPart*)part);
715 case Top: {
716 KHTMLPart *p = part;
717 while (p->parentPart())
718 p = p->parentPart();
719 return retrieve(p);
721 case Crypto:
722 return jsUndefined(); // ###
723 case DefaultStatus:
724 return jsString(UString(part->jsDefaultStatusBarText()));
725 case Status:
726 return jsString(UString(part->jsStatusBarText()));
727 case Document:
728 if (!part->xmlDocImpl()) {
729 kDebug(6070) << "Document.write: adding <HTML><BODY> to create document";
730 part->begin();
731 part->write("<HTML><BODY>");
732 part->end();
734 return getDOMNode(exec, part->xmlDocImpl());
735 case FrameElement:
736 if (m_frame->m_partContainerElement)
737 return getDOMNode(exec,m_frame->m_partContainerElement);
738 else
739 return jsUndefined();
740 case Node:
741 return NodeConstructor::self(exec);
742 case Range:
743 return getRangeConstructor(exec);
744 case NodeFilter:
745 return getNodeFilterConstructor(exec);
746 case NodeList:
747 return NodeListPseudoCtor::self(exec);
748 case DOMException:
749 return getDOMExceptionConstructor(exec);
750 case RangeException:
751 return RangeExceptionPseudoCtor::self(exec);
752 case CSSRule:
753 return getCSSRuleConstructor(exec);
754 case ElementCtor:
755 return ElementPseudoCtor::self(exec);
756 case HTMLElementCtor:
757 return HTMLElementPseudoCtor::self(exec);
758 case HTMLHtmlElementCtor:
759 return HTMLHtmlElementPseudoCtor::self(exec);
760 case HTMLHeadElementCtor:
761 return HTMLHeadElementPseudoCtor::self(exec);
762 case HTMLLinkElementCtor:
763 return HTMLLinkElementPseudoCtor::self(exec);
764 case HTMLTitleElementCtor:
765 return HTMLTitleElementPseudoCtor::self(exec);
766 case HTMLMetaElementCtor:
767 return HTMLMetaElementPseudoCtor::self(exec);
768 case HTMLBaseElementCtor:
769 return HTMLBaseElementPseudoCtor::self(exec);
770 case HTMLIsIndexElementCtor:
771 return HTMLIsIndexElementPseudoCtor::self(exec);
772 case HTMLStyleElementCtor:
773 return HTMLStyleElementPseudoCtor::self(exec);
774 case HTMLBodyElementCtor:
775 return HTMLBodyElementPseudoCtor::self(exec);
776 case HTMLFormElementCtor:
777 return HTMLFormElementPseudoCtor::self(exec);
778 case HTMLSelectElementCtor:
779 return HTMLSelectElementPseudoCtor::self(exec);
780 case HTMLOptGroupElementCtor:
781 return HTMLOptGroupElementPseudoCtor::self(exec);
782 case HTMLOptionElementCtor:
783 return HTMLOptionElementPseudoCtor::self(exec);
784 case HTMLInputElementCtor:
785 return HTMLInputElementPseudoCtor::self(exec);
786 case HTMLTextAreaElementCtor:
787 return HTMLTextAreaElementPseudoCtor::self(exec);
788 case HTMLButtonElementCtor:
789 return HTMLButtonElementPseudoCtor::self(exec);
790 case HTMLLabelElementCtor:
791 return HTMLLabelElementPseudoCtor::self(exec);
792 case HTMLFieldSetElementCtor:
793 return HTMLFieldSetElementPseudoCtor::self(exec);
794 case HTMLLegendElementCtor:
795 return HTMLLegendElementPseudoCtor::self(exec);
796 case HTMLUListElementCtor:
797 return HTMLUListElementPseudoCtor::self(exec);
798 case HTMLOListElementCtor:
799 return HTMLOListElementPseudoCtor::self(exec);
800 case HTMLDListElementCtor:
801 return HTMLDListElementPseudoCtor::self(exec);
802 case HTMLDirectoryElementCtor:
803 return HTMLDirectoryElementPseudoCtor::self(exec);
804 case HTMLMenuElementCtor:
805 return HTMLMenuElementPseudoCtor::self(exec);
806 case HTMLLIElementCtor:
807 return HTMLLIElementPseudoCtor::self(exec);
808 case HTMLDivElementCtor:
809 return HTMLDivElementPseudoCtor::self(exec);
810 case HTMLParagraphElementCtor:
811 return HTMLParagraphElementPseudoCtor::self(exec);
812 case HTMLHeadingElementCtor:
813 return HTMLHeadingElementPseudoCtor::self(exec);
814 case HTMLBlockQuoteElementCtor:
815 return HTMLBlockQuoteElementPseudoCtor::self(exec);
816 case HTMLQuoteElementCtor:
817 return HTMLQuoteElementPseudoCtor::self(exec);
818 case HTMLPreElementCtor:
819 return HTMLPreElementPseudoCtor::self(exec);
820 case HTMLBRElementCtor:
821 return HTMLBRElementPseudoCtor::self(exec);
822 case HTMLBaseFontElementCtor:
823 return HTMLBaseFontElementPseudoCtor::self(exec);
824 case HTMLFontElementCtor:
825 return HTMLFontElementPseudoCtor::self(exec);
826 case HTMLHRElementCtor:
827 return HTMLHRElementPseudoCtor::self(exec);
828 case HTMLModElementCtor:
829 return HTMLModElementPseudoCtor::self(exec);
830 case HTMLAnchorElementCtor:
831 return HTMLAnchorElementPseudoCtor::self(exec);
832 case HTMLImageElementCtor:
833 return HTMLImageElementPseudoCtor::self(exec);
834 case HTMLObjectElementCtor:
835 return HTMLObjectElementPseudoCtor::self(exec);
836 case HTMLParamElementCtor:
837 return HTMLParamElementPseudoCtor::self(exec);
838 case HTMLAppletElementCtor:
839 return HTMLAppletElementPseudoCtor::self(exec);
840 case HTMLMapElementCtor:
841 return HTMLMapElementPseudoCtor::self(exec);
842 case HTMLAreaElementCtor:
843 return HTMLAreaElementPseudoCtor::self(exec);
844 case HTMLScriptElementCtor:
845 return HTMLScriptElementPseudoCtor::self(exec);
846 case HTMLTableElementCtor:
847 return HTMLTableElementPseudoCtor::self(exec);
848 case HTMLTableCaptionElementCtor:
849 return HTMLTableCaptionElementPseudoCtor::self(exec);
850 case HTMLTableColElementCtor:
851 return HTMLTableColElementPseudoCtor::self(exec);
852 case HTMLTableSectionElementCtor:
853 return HTMLTableSectionElementPseudoCtor::self(exec);
854 case HTMLTableRowElementCtor:
855 return HTMLTableRowElementPseudoCtor::self(exec);
856 case HTMLTableCellElementCtor:
857 return HTMLTableCellElementPseudoCtor::self(exec);
858 case HTMLFrameSetElementCtor:
859 return HTMLFrameSetElementPseudoCtor::self(exec);
860 case HTMLLayerElementCtor:
861 return HTMLLayerElementPseudoCtor::self(exec);
862 case HTMLFrameElementCtor:
863 return HTMLFrameElementPseudoCtor::self(exec);
864 case HTMLIFrameElementCtor:
865 return HTMLIFrameElementPseudoCtor::self(exec);
866 case HTMLCollectionCtor:
867 return HTMLCollectionPseudoCtor::self(exec);
868 case HTMLCanvasElementCtor:
869 return HTMLCanvasElementPseudoCtor::self(exec);
870 case Context2DCtor:
871 return Context2DPseudoCtor::self(exec);
872 case DocumentCtor:
873 return DocumentPseudoCtor::self(exec);
874 case HTMLDocumentCtor:
875 return HTMLDocumentPseudoCtor::self(exec);
876 case CSSStyleDeclarationCtor:
877 return CSSStyleDeclarationPseudoCtor::self(exec);
878 case EventCtor:
879 return EventConstructor::self(exec);
880 case MutationEventCtor:
881 return getMutationEventConstructor(exec);
882 case KeyboardEventCtor:
883 return getKeyboardEventConstructor(exec);
884 case EventExceptionCtor:
885 return getEventExceptionConstructor(exec);
886 case _History:
887 return history ? history :
888 (const_cast<Window*>(this)->history = new History(exec,part));
890 case _External:
891 return external ? external :
892 (const_cast<Window*>(this)->external = new External(exec,part));
894 case Event:
895 if (m_evt)
896 return getDOMEvent(exec,m_evt);
897 else {
898 #ifdef KJS_VERBOSE
899 kDebug(6070) << "WARNING: window(" << this << "," << part->objectName() << ").event, no event!";
900 #endif
901 return jsUndefined();
903 case InnerHeight:
905 if (!part->view())
906 return jsUndefined();
907 int ret = part->view()->visibleHeight();
908 // match Gecko which does not subtract the scrollbars
909 if (part->view()->horizontalScrollBar()->isVisible()) {
910 ret += part->view()->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
911 int lvs = part->view()->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
912 if (lvs > 0)
913 ret += lvs;
915 return jsNumber(ret);
917 case InnerWidth:
919 if (!part->view())
920 return jsUndefined();
921 int ret = part->view()->visibleWidth();
922 // match Gecko which does not subtract the scrollbars
923 if (part->view()->verticalScrollBar()->isVisible()) {
924 ret += part->view()->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
925 int lhs = part->view()->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
926 if (lhs > 0)
927 ret += lhs;
929 return jsNumber(ret);
931 case Length:
932 return jsNumber(part->frames().count());
933 case Name:
934 return jsString(part->objectName());
935 case SideBar:
936 return new MozillaSidebarExtension(exec, part);
937 case _Navigator:
938 case ClientInformation: {
939 // Store the navigator in the object so we get the same one each time.
940 JSValue *nav( new Navigator(exec, part) );
941 const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
942 const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
943 return nav;
946 case OffscreenBuffering:
947 return jsBoolean(true);
948 case OuterHeight:
949 case OuterWidth:
951 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
952 if (!part->widget())
953 return jsNumber(0);
954 KWindowInfo inf = KWindowSystem::windowInfo(part->widget()->topLevelWidget()->winId(), NET::WMGeometry);
955 return jsNumber(token == OuterHeight ?
956 inf.geometry().height() : inf.geometry().width());
957 #else
958 return jsNumber(token == OuterHeight ?
959 part->view()->height() : part->view()->width());
960 #endif
962 case PageXOffset:
963 return jsNumber(part->view()->contentsX());
964 case PageYOffset:
965 return jsNumber(part->view()->contentsY());
966 case Personalbar:
967 return jsUndefined(); // ###
968 case ScreenLeft:
969 case ScreenX: {
970 if (!part->view())
971 return jsUndefined();
972 QRect sg = KGlobalSettings::desktopGeometry(part->view());
973 return jsNumber(part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
975 case ScreenTop:
976 case ScreenY: {
977 if (!part->view())
978 return jsUndefined();
979 QRect sg = KGlobalSettings::desktopGeometry(part->view());
980 return jsNumber(part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
982 case ScrollX: {
983 if (!part->view())
984 return jsUndefined();
985 return jsNumber(part->view()->contentsX());
987 case ScrollY: {
988 if (!part->view())
989 return jsUndefined();
990 return jsNumber(part->view()->contentsY());
992 case Scrollbars:
993 return new JSObject(); // ###
994 case _Screen:
995 return screen ? screen :
996 (const_cast<Window*>(this)->screen = new Screen(exec));
997 case Audio:
998 return new AudioConstructorImp(exec, part->xmlDocImpl());
999 case Image:
1000 return new ImageConstructorImp(exec, part->xmlDocImpl());
1001 case Option:
1002 return new OptionConstructorImp(exec, part->xmlDocImpl());
1003 case XMLHttpRequest:
1004 return new XMLHttpRequestConstructorImp(exec, part->xmlDocImpl());
1005 case XMLSerializer:
1006 return new XMLSerializerConstructorImp(exec);
1007 case DOMParser:
1008 return new DOMParserConstructorImp(exec, part->xmlDocImpl());
1009 case Onabort:
1010 return getListener(exec,DOM::EventImpl::ABORT_EVENT);
1011 case Onblur:
1012 return getListener(exec,DOM::EventImpl::BLUR_EVENT);
1013 case Onchange:
1014 return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
1015 case Onclick:
1016 return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
1017 case Ondblclick:
1018 return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
1019 case Ondragdrop:
1020 return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
1021 case Onerror:
1022 return getListener(exec,DOM::EventImpl::ERROR_EVENT);
1023 case Onfocus:
1024 return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
1025 case Onkeydown:
1026 return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
1027 case Onkeypress:
1028 return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
1029 case Onkeyup:
1030 return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
1031 case Onload:
1032 return getListener(exec,DOM::EventImpl::LOAD_EVENT);
1033 case Onmousedown:
1034 return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
1035 case Onmousemove:
1036 return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
1037 case Onmouseout:
1038 return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
1039 case Onmouseover:
1040 return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
1041 case Onmouseup:
1042 return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
1043 case Onmove:
1044 return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
1045 case Onreset:
1046 return getListener(exec,DOM::EventImpl::RESET_EVENT);
1047 case Onresize:
1048 return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
1049 case Onscroll:
1050 return getListener(exec,DOM::EventImpl::SCROLL_EVENT);
1051 case Onselect:
1052 return getListener(exec,DOM::EventImpl::SELECT_EVENT);
1053 case Onsubmit:
1054 return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
1055 case Onunload:
1056 return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
1059 return jsUndefined();
1062 void Window::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int attr)
1064 // we don't want any operations on a closed window
1065 if (m_frame.isNull() || m_frame->m_part.isNull()) {
1066 // ### throw exception? allow setting of some props like location?
1067 return;
1070 // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
1071 // If yes, save time and jump directly to JSObject. We also have
1072 // to do this now since calling isSafeScript() may not work yet.
1073 if (attr != None && attr != DontDelete)
1075 JSObject::put( exec, propertyName, value, attr );
1076 return;
1080 // If we already have a variable, that's writeable w/o a getter/setter mess, just write to it.
1081 bool safe = isSafeScript(exec);
1082 if (safe) {
1083 if (JSValue** slot = getDirectWriteLocation(propertyName)) {
1084 *slot = value;
1085 return;
1089 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
1090 if (entry && !m_frame.isNull() && !m_frame->m_part.isNull())
1092 #ifdef KJS_VERBOSE
1093 kDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring();
1094 #endif
1095 switch( entry->value) {
1096 case _Location:
1097 goURL(exec, value->toString(exec).qstring(), false /*don't lock history*/);
1098 return;
1099 default:
1100 break;
1102 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1103 if (part) {
1104 switch( entry->value ) {
1105 case Status: {
1106 if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
1107 == KHTMLSettings::KJSWindowStatusAllow) {
1108 UString s = value->toString(exec);
1109 part->setJSStatusBarText(s.qstring());
1111 return;
1113 case DefaultStatus: {
1114 if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
1115 == KHTMLSettings::KJSWindowStatusAllow) {
1116 UString s = value->toString(exec);
1117 part->setJSDefaultStatusBarText(s.qstring());
1119 return;
1121 case Onabort:
1122 if (isSafeScript(exec))
1123 setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
1124 return;
1125 case Onblur:
1126 if (isSafeScript(exec))
1127 setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
1128 return;
1129 case Onchange:
1130 if (isSafeScript(exec))
1131 setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
1132 return;
1133 case Onclick:
1134 if (isSafeScript(exec))
1135 setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
1136 return;
1137 case Ondblclick:
1138 if (isSafeScript(exec))
1139 setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
1140 return;
1141 case Ondragdrop:
1142 if (isSafeScript(exec))
1143 setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
1144 return;
1145 case Onerror:
1146 if (isSafeScript(exec))
1147 setListener(exec,DOM::EventImpl::ERROR_EVENT,value);
1148 return;
1149 case Onfocus:
1150 if (isSafeScript(exec))
1151 setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
1152 return;
1153 case Onkeydown:
1154 if (isSafeScript(exec))
1155 setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
1156 return;
1157 case Onkeypress:
1158 if (isSafeScript(exec))
1159 setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
1160 return;
1161 case Onkeyup:
1162 if (isSafeScript(exec))
1163 setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
1164 return;
1165 case Onload:
1166 if (isSafeScript(exec))
1167 setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
1168 return;
1169 case Onmousedown:
1170 if (isSafeScript(exec))
1171 setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
1172 return;
1173 case Onmousemove:
1174 if (isSafeScript(exec))
1175 setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
1176 return;
1177 case Onmouseout:
1178 if (isSafeScript(exec))
1179 setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
1180 return;
1181 case Onmouseover:
1182 if (isSafeScript(exec))
1183 setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
1184 return;
1185 case Onmouseup:
1186 if (isSafeScript(exec))
1187 setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
1188 return;
1189 case Onmove:
1190 if (isSafeScript(exec))
1191 setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
1192 return;
1193 case Onreset:
1194 if (isSafeScript(exec))
1195 setListener(exec,DOM::EventImpl::RESET_EVENT,value);
1196 return;
1197 case Onresize:
1198 if (isSafeScript(exec))
1199 setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
1200 return;
1201 case Onscroll:
1202 if (isSafeScript(exec))
1203 setListener(exec,DOM::EventImpl::SCROLL_EVENT,value);
1204 return;
1205 case Onselect:
1206 if (isSafeScript(exec))
1207 setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
1208 return;
1209 case Onsubmit:
1210 if (isSafeScript(exec))
1211 setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
1212 return;
1213 case Onunload:
1214 if (isSafeScript(exec))
1215 setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
1216 return;
1217 case Name:
1218 if (isSafeScript(exec))
1219 part->setObjectName( value->toString(exec).qstring().toLocal8Bit().data() );
1220 return;
1221 default:
1222 break;
1226 if (m_frame->m_liveconnect &&
1227 isSafeScript(exec) &&
1228 m_frame->m_liveconnect->put(0, propertyName.qstring(), value->toString(exec).qstring()))
1229 return;
1230 if (safe) {
1231 //kDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring();
1232 JSObject::put(exec, propertyName, value, attr);
1236 bool Window::toBoolean(ExecState *) const
1238 return !m_frame.isNull() && !m_frame->m_part.isNull();
1241 DOM::AbstractViewImpl* Window::toAbstractView() const
1243 KHTMLPart *part = ::qobject_cast<KHTMLPart *>(m_frame->m_part);
1244 if (!part || !part->xmlDocImpl())
1245 return 0;
1246 return part->xmlDocImpl()->defaultView();
1249 void Window::scheduleClose()
1251 kDebug(6070) << "Window::scheduleClose window.close() " << m_frame;
1252 Q_ASSERT(winq);
1253 QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
1256 void Window::closeNow()
1258 if (m_frame.isNull() || m_frame->m_part.isNull()) {
1259 kDebug(6070) << "part is deleted already";
1260 } else {
1261 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1262 if (!part) {
1263 kDebug(6070) << "closeNow on non KHTML part";
1264 } else {
1265 //kDebug(6070) << " -> closing window";
1266 // We want to make sure that window.open won't find this part by name.
1267 part->setObjectName( QString() );
1268 part->deleteLater();
1269 part = 0;
1274 void Window::afterScriptExecution()
1276 DOM::DocumentImpl::updateDocumentsRendering();
1277 const QList<DelayedAction> delayedActions = m_delayed;
1278 m_delayed.clear();
1279 QList<DelayedAction>::ConstIterator it = delayedActions.begin();
1280 for ( ; it != delayedActions.end() ; ++it )
1282 switch ((*it).actionId) {
1283 case DelayedClose:
1284 scheduleClose();
1285 return; // stop here, in case of multiple actions
1286 case DelayedGoHistory:
1287 goHistory( (*it).param.toInt() );
1288 break;
1289 case NullAction:
1290 // FIXME: anything needs to be done here? This is warning anyways.
1291 break;
1296 bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const
1298 if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access
1299 kDebug(6070) << "Window::isSafeScript: accessing deleted part !";
1300 return false;
1302 if (!activePart) {
1303 kDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!";
1304 return false;
1306 if ( activePart == m_frame->m_part ) // Not calling from another frame, no problem.
1307 return true;
1309 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1310 if (!part)
1311 return true; // not a KHTMLPart
1313 if ( !part->xmlDocImpl() )
1314 return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
1316 DOM::DocumentImpl* thisDocument = part->xmlDocImpl();
1318 KHTMLPart *activeKHTMLPart = qobject_cast<KHTMLPart*>(activePart);
1319 if (!activeKHTMLPart)
1320 return true; // not a KHTMLPart
1322 DOM::DocumentImpl* actDocument = activeKHTMLPart->xmlDocImpl();
1323 if ( !actDocument ) {
1324 kDebug(6070) << "Window::isSafeScript: active part has no document!";
1325 return false;
1327 DOM::DOMString actDomain = actDocument->domain();
1328 DOM::DOMString thisDomain = thisDocument->domain();
1330 if ( actDomain == thisDomain ) {
1331 #ifdef KJS_VERBOSE
1332 //kDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'";
1333 #endif
1334 return true;
1337 kDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'";
1338 // TODO after 3.1: throw security exception (exec->setException())
1339 return false;
1342 void Window::setListener(ExecState *exec, int eventId, JSValue *func)
1344 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1345 if (!part || !isSafeScript(exec))
1346 return;
1347 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
1348 if (!doc)
1349 return;
1351 doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
1354 JSValue *Window::getListener(ExecState *exec, int eventId) const
1356 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1357 if (!part || !isSafeScript(exec))
1358 return jsUndefined();
1359 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
1360 if (!doc)
1361 return jsUndefined();
1363 DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
1364 if (listener && static_cast<JSEventListener*>(listener)->listenerObj())
1365 return static_cast<JSEventListener*>(listener)->listenerObj();
1366 else
1367 return jsNull();
1371 JSEventListener *Window::getJSEventListener(JSValue *val, bool html)
1373 // This function is so hot that it's worth coding it directly with imps.
1374 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1375 if (!part || val->type() != ObjectType)
1376 return 0;
1378 // It's ObjectType, so it must be valid.
1379 JSObject *listenerObject = val->getObject();
1380 JSObject *thisObject = listenerObject;
1382 // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!)
1383 if (!listenerObject->implementsCall() && part && part->jScript() && part->jScript()->interpreter())
1385 Interpreter *interpreter = part->jScript()->interpreter();
1387 // 'listener' probably is an EventListener object containing a 'handleEvent' function.
1388 JSValue *handleEventValue = listenerObject->get(interpreter->globalExec(), Identifier("handleEvent"));
1389 JSObject *handleEventObject = handleEventValue->getObject();
1391 if(handleEventObject && handleEventObject->implementsCall())
1393 thisObject = listenerObject;
1394 listenerObject = handleEventObject;
1398 JSEventListener *existingListener = jsEventListeners[QPair<void*, bool>(thisObject, html)];
1399 if (existingListener) {
1400 assert( existingListener->isHTMLEventListener() == html );
1401 return existingListener;
1404 // Note that the JSEventListener constructor adds it to our jsEventListeners list
1405 return new JSEventListener(listenerObject, thisObject, this, html);
1408 JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, const QString& srcUrl, int line,
1409 const QString& name, DOM::NodeImpl *node, bool svg)
1411 return new JSLazyEventListener(code, srcUrl, line, name, this, node, svg);
1414 void Window::clear( ExecState *exec )
1416 delete winq;
1417 winq = 0L;
1418 // Get rid of everything, those user vars could hold references to DOM nodes
1419 clearProperties();
1421 // Ditto for the special subobjects.
1422 screen = 0;
1423 history = 0;
1424 external = 0;
1425 loc = 0;
1426 setPrototype(jsNull());
1428 // Break the dependency between the listeners and their object
1429 QHashIterator<const QPair<void*, bool>, JSEventListener*> it(jsEventListeners);
1430 while ( it.hasNext() ) {
1431 it.next();
1432 it.value()->clear();
1435 // Forget about the listeners (the DOM::NodeImpls will delete them)
1436 jsEventListeners.clear();
1438 if (m_frame) {
1439 KJSProxy* proxy = m_frame->m_jscript;
1440 if (proxy) // i.e. JS not disabled
1442 winq = new WindowQObject(this);
1443 // Now recreate a working global object for the next URL that will use us
1444 KJS::Interpreter *interpreter = proxy->interpreter();
1445 interpreter->initGlobalObject();
1450 void Window::setCurrentEvent( DOM::EventImpl *evt )
1452 m_evt = evt;
1453 //kDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt;
1456 void Window::goURL(ExecState* exec, const QString& url, bool lockHistory)
1458 Window* active = Window::retrieveActive(exec);
1459 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1460 KHTMLPart *active_part = qobject_cast<KHTMLPart*>(active->part());
1461 // Complete the URL using the "active part" (running interpreter)
1462 if (active_part && part) {
1463 QString dstUrl = active_part->htmlDocument().completeURL(url).string();
1464 kDebug(6070) << "Window::goURL dstUrl=" << dstUrl;
1466 // check if we're allowed to inject javascript
1467 if ( isSafeScript(exec) ||
1468 !KHTMLPartPrivate::isJavaScriptURL(dstUrl) )
1469 part->scheduleRedirection(-1,
1470 dstUrl,
1471 lockHistory);
1472 } else if (!part && m_frame->m_partContainerElement) {
1473 KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part);
1474 if (b)
1475 emit b->openUrlRequest(m_frame->m_partContainerElement->document()->completeURL(url));
1476 kDebug() << "goURL for ROPart";
1480 void Window::delayedGoHistory( int steps )
1482 m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
1485 void Window::goHistory( int steps )
1487 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1488 if(!part)
1489 // TODO history readonlypart
1490 return;
1491 KParts::BrowserExtension *ext = part->browserExtension();
1492 if(!ext)
1493 return;
1494 KParts::BrowserInterface *iface = ext->browserInterface();
1496 if ( !iface )
1497 return;
1499 iface->callMethod( "goHistory", steps );
1500 //emit ext->goHistory(steps);
1503 void KJS::Window::resizeTo(QWidget* tl, int width, int height)
1505 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1506 if(!part)
1507 // TODO resizeTo readonlypart
1508 return;
1509 KParts::BrowserExtension *ext = part->browserExtension();
1510 if (!ext) {
1511 kDebug(6070) << "Window::resizeTo found no browserExtension";
1512 return;
1515 // Security check: within desktop limits and bigger than 100x100 (per spec)
1516 if ( width < 100 || height < 100 ) {
1517 kDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")";
1518 return;
1521 QRect sg = KGlobalSettings::desktopGeometry(tl);
1523 if ( width > sg.width() || height > sg.height() ) {
1524 kDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")";
1525 return;
1528 kDebug(6070) << "resizing to " << width << "x" << height;
1530 emit ext->resizeTopLevelWidget( width, height );
1532 // If the window is out of the desktop, move it up/left
1533 // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
1534 int right = tl->x() + tl->frameGeometry().width();
1535 int bottom = tl->y() + tl->frameGeometry().height();
1536 int moveByX = 0;
1537 int moveByY = 0;
1538 if ( right > sg.right() )
1539 moveByX = - right + sg.right(); // always <0
1540 if ( bottom > sg.bottom() )
1541 moveByY = - bottom + sg.bottom(); // always <0
1542 if ( moveByX || moveByY )
1543 emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY );
1546 bool Window::targetIsExistingWindow(KHTMLPart* ourPart, const QString& frameName)
1548 QString normalized = frameName.toLower();
1549 if (normalized == "_top" || normalized == "_self" || normalized == "_parent")
1550 return true;
1552 // Find the highest parent part we can access.
1553 KHTMLPart* p = ourPart;
1554 while (p->parentPart() && p->parentPart()->checkFrameAccess(ourPart))
1555 p = p->parentPart();
1557 return p->findFrame(frameName);
1560 JSValue *Window::openWindow(ExecState *exec, const List& args)
1562 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1563 if (!part)
1564 return jsUndefined();
1565 KHTMLView *widget = part->view();
1566 JSValue *v = args[0];
1567 QString str;
1568 if (!v->isUndefinedOrNull())
1569 str = v->toString(exec).qstring();
1571 // prepare arguments
1572 KUrl url;
1573 if (!str.isEmpty())
1575 KHTMLPart* p = qobject_cast<KHTMLPart*>(Window::retrieveActive(exec)->m_frame->m_part);
1576 if ( p )
1577 url = p->htmlDocument().completeURL(str).string();
1578 if ( !p ||
1579 !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
1580 return jsUndefined();
1583 KHTMLSettings::KJSWindowOpenPolicy policy =
1584 part->settings()->windowOpenPolicy(part->url().host());
1586 QString frameName = args.size() > 1 ? args[1]->toString(exec).qstring() : QString("_blank");
1588 // Always permit opening in an exist frame (including _self, etc.)
1589 if ( targetIsExistingWindow( part, frameName ) )
1590 policy = KHTMLSettings::KJSWindowOpenAllow;
1592 if ( policy == KHTMLSettings::KJSWindowOpenAsk ) {
1593 emit part->browserExtension()->requestFocus(part);
1594 QString caption;
1595 if (!part->url().host().isEmpty())
1596 caption = part->url().host() + " - ";
1597 caption += i18n( "Confirmation: JavaScript Popup" );
1598 if ( KMessageBox::questionYesNo(widget,
1599 str.isEmpty() ?
1600 i18n( "This site is requesting to open up a new browser "
1601 "window via JavaScript.\n"
1602 "Do you want to allow this?" ) :
1603 i18n( "<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />"
1604 "Do you want to allow this?</qt>", KStringHandler::csqueeze(Qt::escape(url.prettyUrl()), 100)),
1605 caption, KGuiItem(i18n("Allow")), KGuiItem(i18n("Do Not Allow")) ) == KMessageBox::Yes )
1606 policy = KHTMLSettings::KJSWindowOpenAllow;
1607 } else if ( policy == KHTMLSettings::KJSWindowOpenSmart )
1609 // window.open disabled unless from a key/mouse event
1610 if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->isWindowOpenAllowed())
1611 policy = KHTMLSettings::KJSWindowOpenAllow;
1614 v = args[2];
1615 QString features;
1616 if (v && v->type() != UndefinedType && v->toString(exec).size() > 0) {
1617 features = v->toString(exec).qstring();
1618 // Buggy scripts have ' at beginning and end, cut those
1619 if (features.startsWith(QLatin1Char('\'')) &&
1620 features.endsWith(QLatin1Char('\'')))
1621 features = features.mid(1, features.length()-2);
1624 if ( policy != KHTMLSettings::KJSWindowOpenAllow ) {
1625 if ( url.isEmpty() )
1626 part->setSuppressedPopupIndicator(true, 0);
1627 else {
1628 part->setSuppressedPopupIndicator(true, part);
1629 m_suppressedWindowInfo.append( SuppressedWindowInfo( url, frameName, features ) );
1631 return jsUndefined();
1632 } else {
1633 return executeOpenWindow(exec, url, frameName, features);
1637 JSValue *Window::executeOpenWindow(ExecState *exec, const KUrl& url, const QString& frameName, const QString& features)
1639 KHTMLPart *p = qobject_cast<KHTMLPart *>(m_frame->m_part);
1640 KHTMLView *widget = p->view();
1641 KParts::WindowArgs winargs;
1643 // scan feature argument
1644 if (!features.isEmpty()) {
1645 // specifying window params means false defaults
1646 winargs.setMenuBarVisible(false);
1647 winargs.setToolBarsVisible(false);
1648 winargs.setStatusBarVisible(false);
1649 winargs.setScrollBarsVisible(false);
1650 const QStringList flist = features.split(',');
1651 QStringList::ConstIterator it = flist.begin();
1652 while (it != flist.end()) {
1653 QString s = *it++;
1654 QString key, val;
1655 int pos = s.indexOf('=');
1656 if (pos >= 0) {
1657 key = s.left(pos).trimmed().toLower();
1658 val = s.mid(pos + 1).trimmed().toLower();
1659 QRect screen = KGlobalSettings::desktopGeometry(widget->topLevelWidget());
1661 if (key == "left" || key == "screenx") {
1662 winargs.setX((int)val.toFloat() + screen.x());
1663 if (winargs.x() < screen.x() || winargs.x() > screen.right())
1664 winargs.setX(screen.x()); // only safe choice until size is determined
1665 } else if (key == "top" || key == "screeny") {
1666 winargs.setY((int)val.toFloat() + screen.y());
1667 if (winargs.y() < screen.y() || winargs.y() > screen.bottom())
1668 winargs.setY(screen.y()); // only safe choice until size is determined
1669 } else if (key == "height") {
1670 winargs.setHeight((int)val.toFloat() + 2*qApp->style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2);
1671 if (winargs.height() > screen.height()) // should actually check workspace
1672 winargs.setHeight(screen.height());
1673 if (winargs.height() < 100)
1674 winargs.setHeight(100);
1675 } else if (key == "width") {
1676 winargs.setWidth((int)val.toFloat() + 2*qApp->style()->pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2);
1677 if (winargs.width() > screen.width()) // should actually check workspace
1678 winargs.setWidth(screen.width());
1679 if (winargs.width() < 100)
1680 winargs.setWidth(100);
1681 } else {
1682 goto boolargs;
1684 continue;
1685 } else {
1686 // leaving away the value gives true
1687 key = s.trimmed().toLower();
1688 val = "1";
1690 boolargs:
1691 if (key == "menubar")
1692 winargs.setMenuBarVisible(val == "1" || val == "yes");
1693 else if (key == "toolbar")
1694 winargs.setToolBarsVisible(val == "1" || val == "yes");
1695 else if (key == "location") // ### missing in WindowArgs
1696 winargs.setToolBarsVisible(val == "1" || val == "yes");
1697 else if (key == "status" || key == "statusbar")
1698 winargs.setStatusBarVisible(val == "1" || val == "yes");
1699 else if (key == "scrollbars")
1700 winargs.setScrollBarsVisible(val == "1" || val == "yes");
1701 else if (key == "resizable")
1702 winargs.setResizable(val == "1" || val == "yes");
1703 else if (key == "fullscreen")
1704 winargs.setFullScreen(val == "1" || val == "yes");
1708 KParts::OpenUrlArguments args;
1709 KParts::BrowserArguments browserArgs;
1710 browserArgs.frameName = frameName;
1712 if ( browserArgs.frameName.toLower() == "_top" )
1714 while ( p->parentPart() )
1715 p = p->parentPart();
1716 Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
1717 return Window::retrieve(p);
1719 if ( browserArgs.frameName.toLower() == "_parent" )
1721 if ( p->parentPart() )
1722 p = p->parentPart();
1723 Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
1724 return Window::retrieve(p);
1726 if ( browserArgs.frameName.toLower() == "_self")
1728 Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
1729 return Window::retrieve(p);
1731 if ( browserArgs.frameName.toLower() == "replace" )
1733 Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/);
1734 return Window::retrieve(p);
1736 args.setMimeType("text/html");
1737 args.setActionRequestedByUser(false);
1739 // request window (new or existing if framename is set)
1740 KParts::ReadOnlyPart *newPart = 0;
1741 emit p->browserExtension()->createNewWindow(KUrl(), args, browserArgs, winargs, &newPart);
1742 if (newPart && qobject_cast<KHTMLPart*>(newPart)) {
1743 KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
1744 //qDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window);
1745 khtmlpart->setOpener(p);
1746 khtmlpart->setOpenedByJS(true);
1747 if (khtmlpart->document().isNull()) {
1748 khtmlpart->begin();
1749 khtmlpart->write("<HTML><BODY>");
1750 khtmlpart->end();
1751 if ( p->docImpl() ) {
1752 //kDebug(6070) << "Setting domain to " << p->docImpl()->domain().string();
1753 khtmlpart->docImpl()->setDomain( p->docImpl()->domain());
1754 khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
1757 args.setMimeType(QString());
1758 if (browserArgs.frameName.toLower() == "_blank")
1759 browserArgs.frameName.clear();
1760 if (!url.isEmpty())
1761 emit khtmlpart->browserExtension()->openUrlRequest(url, args, browserArgs);
1762 return Window::retrieve(khtmlpart); // global object
1763 } else
1764 return jsUndefined();
1767 void Window::forgetSuppressedWindows()
1769 m_suppressedWindowInfo.clear();
1772 void Window::showSuppressedWindows()
1774 KHTMLPart *part = qobject_cast<KHTMLPart*>(m_frame->m_part);
1775 KJS::Interpreter *interpreter = part->jScript()->interpreter();
1776 ExecState *exec = interpreter->globalExec();
1778 QList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo;
1779 m_suppressedWindowInfo.clear();
1780 foreach ( const SuppressedWindowInfo &info, suppressedWindowInfo ) {
1781 executeOpenWindow(exec, info.url, info.frameName, info.features);
1785 JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
1787 KJS_CHECK_THIS( Window, thisObj );
1789 // these should work no matter whether the window is already
1790 // closed or not
1791 if (id == Window::ValueOf || id == Window::ToString) {
1792 return jsString("[object Window]");
1795 Window *window = static_cast<Window *>(thisObj);
1796 QString str, str2;
1798 KHTMLPart *part = qobject_cast<KHTMLPart*>(window->m_frame->m_part);
1799 if (!part)
1800 return jsUndefined();
1802 KHTMLView *widget = part->view();
1803 JSValue *v = args[0];
1804 UString s;
1805 if (!v->isUndefinedOrNull()) {
1806 s = v->toString(exec);
1807 str = s.qstring();
1810 QString caption;
1811 if (part && !part->url().host().isEmpty())
1812 caption = part->url().host() + " - ";
1813 caption += "JavaScript"; // TODO: i18n
1814 // functions that work everywhere
1815 switch(id) {
1816 case Window::Alert: {
1817 TimerPauser pause(exec);
1818 if (!widget->dialogsAllowed())
1819 return jsUndefined();
1820 if ( part && part->xmlDocImpl() )
1821 part->xmlDocImpl()->updateRendering();
1822 if ( part )
1823 emit part->browserExtension()->requestFocus(part);
1824 KMessageBox::error(widget, Qt::convertFromPlainText(str, Qt::WhiteSpaceNormal), caption);
1825 return jsUndefined();
1827 case Window::Confirm: {
1828 TimerPauser pause(exec);
1829 if (!widget->dialogsAllowed())
1830 return jsUndefined();
1831 if ( part && part->xmlDocImpl() )
1832 part->xmlDocImpl()->updateRendering();
1833 if ( part )
1834 emit part->browserExtension()->requestFocus(part);
1835 return jsBoolean((KMessageBox::warningYesNo(widget, Qt::convertFromPlainText(str), caption,
1836 KStandardGuiItem::ok(), KStandardGuiItem::cancel()) == KMessageBox::Yes));
1838 case Window::Prompt: {
1839 TimerPauser pause(exec);
1840 #ifndef KONQ_EMBEDDED
1841 if (!widget->dialogsAllowed())
1842 return jsUndefined();
1843 if ( part && part->xmlDocImpl() )
1844 part->xmlDocImpl()->updateRendering();
1845 if ( part )
1846 emit part->browserExtension()->requestFocus(part);
1847 bool ok;
1848 if (args.size() >= 2)
1849 str2 = KInputDialog::getText(caption,
1850 Qt::convertFromPlainText(str),
1851 args[1]->toString(exec).qstring(), &ok, widget);
1852 else
1853 str2 = KInputDialog::getText(caption,
1854 Qt::convertFromPlainText(str),
1855 QString(), &ok, widget);
1856 if ( ok )
1857 return jsString(UString(str2));
1858 else
1859 return jsNull();
1860 #else
1861 return jsUndefined();
1862 #endif
1864 case Window::GetComputedStyle: {
1865 if ( !part || !part->xmlDocImpl() )
1866 return jsUndefined();
1867 DOM::NodeImpl* arg0 = toNode(args[0]);
1868 if (!arg0 || arg0->nodeType() != DOM::Node::ELEMENT_NODE)
1869 return jsUndefined(); // throw exception?
1870 else
1871 return getDOMCSSStyleDeclaration(exec, part->xmlDocImpl()->defaultView()->getComputedStyle(
1872 static_cast<DOM::ElementImpl*>(arg0), args[1]->toString(exec).domString().implementation()));
1874 case Window::Open:
1875 return window->openWindow(exec, args);
1876 case Window::Close: {
1877 /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
1878 The close method closes only windows opened by JavaScript using the open method.
1879 If you attempt to close any other window, a confirm is generated, which
1880 lets the user choose whether the window closes.
1881 This is a security feature to prevent "mail bombs" containing self.close().
1882 However, if the window has only one document (the current one) in its
1883 session history, the close is allowed without any confirm. This is a
1884 special case for one-off windows that need to open other windows and
1885 then dispose of themselves.
1887 bool doClose = false;
1888 if (!part->openedByJS())
1890 // To conform to the SPEC, we only ask if the window
1891 // has more than one entry in the history (NS does that too).
1892 History history(exec,part);
1894 if ( history.get( exec, "length" )->toInt32(exec) <= 1 )
1896 doClose = true;
1898 else
1900 // Can we get this dialog with tabs??? Does it close the window or the tab in that case?
1901 emit part->browserExtension()->requestFocus(part);
1902 if ( KMessageBox::questionYesNo( window->part()->widget(),
1903 i18n("Close window?"), i18n("Confirmation Required"),
1904 KStandardGuiItem::close(), KStandardGuiItem::cancel() )
1905 == KMessageBox::Yes )
1906 doClose = true;
1909 else
1910 doClose = true;
1912 if (doClose)
1914 // If this is the current window (the one the interpreter runs in),
1915 // then schedule a delayed close (so that the script terminates first).
1916 // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
1917 if ( Window::retrieveActive(exec) == window ) {
1918 if (widget) {
1919 // quit all dialogs of this view
1920 // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
1921 widget->closeChildDialogs();
1923 //kDebug() << "scheduling delayed close";
1924 // We'll close the window at the end of the script execution
1925 Window* w = const_cast<Window*>(window);
1926 w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
1927 } else {
1928 //kDebug() << "closing NOW";
1929 (const_cast<Window*>(window))->closeNow();
1932 return jsUndefined();
1934 case Window::Navigate:
1935 window->goURL(exec, args[0]->toString(exec).qstring(), false /*don't lock history*/);
1936 return jsUndefined();
1937 case Window::Focus: {
1938 KHTMLSettings::KJSWindowFocusPolicy policy =
1939 part->settings()->windowFocusPolicy(part->url().host());
1940 if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) {
1941 widget->topLevelWidget()->raise();
1942 #ifdef Q_WS_X11
1943 KWindowSystem::unminimizeWindow( widget->topLevelWidget()->winId() );
1944 #else
1945 //TODO
1946 #endif
1947 widget->activateWindow();
1948 emit part->browserExtension()->requestFocus(part);
1950 return jsUndefined();
1952 case Window::Blur:
1953 // TODO
1954 return jsUndefined();
1955 case Window::BToA:
1956 case Window::AToB: {
1957 if (!s.is8Bit())
1958 return jsUndefined();
1959 QByteArray in, out;
1960 char *binData = s.ascii();
1961 in = QByteArray( binData, s.size() );
1962 if (id == Window::AToB)
1963 out = QByteArray::fromBase64(in);
1964 else
1965 out = in.toBase64();
1966 UChar *d = new UChar[out.size()];
1967 for (int i = 0; i < out.size(); i++)
1968 d[i].uc = (uchar) out[i];
1969 UString ret(d, out.size(), false /*no copy*/);
1970 return jsString(ret);
1976 // now unsafe functions..
1977 if (!window->isSafeScript(exec))
1978 return jsUndefined();
1980 switch (id) {
1981 case Window::ScrollBy:
1982 if(args.size() == 2 && widget)
1983 widget->scrollBy(args[0]->toInt32(exec), args[1]->toInt32(exec));
1984 return jsUndefined();
1985 case Window::Scroll:
1986 case Window::ScrollTo:
1987 if(args.size() == 2 && widget)
1988 widget->setContentsPos(args[0]->toInt32(exec), args[1]->toInt32(exec));
1989 return jsUndefined();
1990 case Window::MoveBy: {
1991 KHTMLSettings::KJSWindowMovePolicy policy =
1992 part->settings()->windowMovePolicy(part->url().host());
1993 if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
1995 KParts::BrowserExtension *ext = part->browserExtension();
1996 if (ext) {
1997 QWidget * tl = widget->topLevelWidget();
1998 QRect sg = KGlobalSettings::desktopGeometry(tl);
2000 QPoint dest = tl->pos() + QPoint( args[0]->toInt32(exec), args[1]->toInt32(exec) );
2001 // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
2002 if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
2003 dest.x()+tl->width() <= sg.width()+sg.x() &&
2004 dest.y()+tl->height() <= sg.height()+sg.y() )
2005 emit ext->moveTopLevelWidget( dest.x(), dest.y() );
2008 return jsUndefined();
2010 case Window::MoveTo: {
2011 KHTMLSettings::KJSWindowMovePolicy policy =
2012 part->settings()->windowMovePolicy(part->url().host());
2013 if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
2015 KParts::BrowserExtension *ext = part->browserExtension();
2016 if (ext) {
2017 QWidget * tl = widget->topLevelWidget();
2018 QRect sg = KGlobalSettings::desktopGeometry(tl);
2020 QPoint dest( args[0]->toInt32(exec)+sg.x(), args[1]->toInt32(exec)+sg.y() );
2021 // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
2022 if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
2023 dest.x()+tl->width() <= sg.width()+sg.x() &&
2024 dest.y()+tl->height() <= sg.height()+sg.y() )
2025 emit ext->moveTopLevelWidget( dest.x(), dest.y() );
2028 return jsUndefined();
2030 case Window::ResizeBy: {
2031 KHTMLSettings::KJSWindowResizePolicy policy =
2032 part->settings()->windowResizePolicy(part->url().host());
2033 if(policy == KHTMLSettings::KJSWindowResizeAllow
2034 && args.size() == 2 && widget)
2036 QWidget * tl = widget->topLevelWidget();
2037 QRect geom = tl->frameGeometry();
2038 window->resizeTo( tl,
2039 geom.width() + args[0]->toInt32(exec),
2040 geom.height() + args[1]->toInt32(exec) );
2042 return jsUndefined();
2044 case Window::ResizeTo: {
2045 KHTMLSettings::KJSWindowResizePolicy policy =
2046 part->settings()->windowResizePolicy(part->url().host());
2047 if(policy == KHTMLSettings::KJSWindowResizeAllow
2048 && args.size() == 2 && widget)
2050 QWidget * tl = widget->topLevelWidget();
2051 window->resizeTo( tl, args[0]->toInt32(exec), args[1]->toInt32(exec) );
2053 return jsUndefined();
2055 case Window::SetTimeout:
2056 case Window::SetInterval: {
2057 bool singleShot;
2058 int i; // timeout interval
2059 if (args.size() == 0)
2060 return jsUndefined();
2061 if (args.size() > 1) {
2062 singleShot = (id == Window::SetTimeout);
2063 i = args[1]->toInt32(exec);
2064 } else {
2065 // second parameter is missing. Emulate Mozilla behavior.
2066 singleShot = true;
2067 i = 4;
2069 if (v->type() == StringType) {
2070 int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot );
2071 return jsNumber(r);
2073 else if (v->type() == ObjectType && v->getObject()->implementsCall()) {
2074 JSObject *func = v->getObject();
2075 List funcArgs;
2076 ListIterator it = args.begin();
2077 int argno = 0;
2078 while (it != args.end()) {
2079 JSValue *arg = it++;
2080 if (argno++ >= 2)
2081 funcArgs.append(arg);
2083 if (args.size() < 2)
2084 funcArgs.append(jsNumber(i));
2085 int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot );
2086 return jsNumber(r);
2088 else
2089 return jsUndefined();
2091 case Window::ClearTimeout:
2092 case Window::ClearInterval:
2093 (const_cast<Window*>(window))->winq->clearTimeout(v->toInt32(exec));
2094 return jsUndefined();
2095 case Window::Print:
2096 if ( widget ) {
2097 // ### TODO emit onbeforeprint event
2098 widget->print();
2099 // ### TODO emit onafterprint event
2101 case Window::CaptureEvents:
2102 case Window::ReleaseEvents:
2103 // Do nothing for now. These are NS-specific legacy calls.
2104 break;
2105 case Window::AddEventListener: {
2106 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
2107 if (listener) {
2108 DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
2109 docimpl->addWindowEventListener(EventName::fromString(args[0]->toString(exec).domString()),listener,args[2]->toBoolean(exec));
2111 return jsUndefined();
2113 case Window::RemoveEventListener: {
2114 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
2115 if (listener) {
2116 DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
2117 docimpl->removeWindowEventListener(EventName::fromString(args[0]->toString(exec).domString()),listener,args[2]->toBoolean(exec));
2119 return jsUndefined();
2123 return jsUndefined();
2126 ////////////////////// ScheduledAction ////////////////////////
2128 // KDE 4: Make those parameters const ... &
2129 ScheduledAction::ScheduledAction(JSObject* _func, List _args, DateTimeMS _nextTime, int _interval, bool _singleShot,
2130 int _timerId)
2132 //kDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this;
2133 func = static_cast<JSObject*>(_func);
2134 args = _args;
2135 isFunction = true;
2136 singleShot = _singleShot;
2137 nextTime = _nextTime;
2138 interval = _interval;
2139 executing = false;
2140 timerId = _timerId;
2143 // KDE 4: Make it const QString &
2144 ScheduledAction::ScheduledAction(QString _code, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId)
2146 //kDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this;
2147 //func = 0;
2148 //args = 0;
2149 func = 0;
2150 code = _code;
2151 isFunction = false;
2152 singleShot = _singleShot;
2153 nextTime = _nextTime;
2154 interval = _interval;
2155 executing = false;
2156 timerId = _timerId;
2159 bool ScheduledAction::execute(Window *window)
2161 KHTMLPart *part = qobject_cast<KHTMLPart*>(window->m_frame->m_part);
2162 if (!part || !part->jScriptEnabled())
2163 return false;
2164 ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter());
2166 interpreter->setProcessingTimerCallback(true);
2168 //kDebug(6070) << "ScheduledAction::execute " << this;
2169 if (isFunction) {
2170 if (func->implementsCall()) {
2171 // #### check this
2172 Q_ASSERT( part );
2173 if ( part )
2175 KJS::Interpreter *interpreter = part->jScript()->interpreter();
2176 ExecState *exec = interpreter->globalExec();
2177 Q_ASSERT( window == interpreter->globalObject() );
2178 JSObject *obj( window );
2179 func->call(exec,obj,args); // note that call() creates its own execution state for the func call
2180 if (exec->hadException())
2181 exec->clearException();
2183 // Update our document's rendering following the execution of the timeout callback.
2184 part->document().updateRendering();
2188 else {
2189 part->executeScript(DOM::Node(), code);
2192 interpreter->setProcessingTimerCallback(false);
2193 return true;
2196 void ScheduledAction::mark()
2198 if (func && !func->marked())
2199 func->mark();
2202 ScheduledAction::~ScheduledAction()
2204 args.reset();
2205 //kDebug(6070) << "ScheduledAction::~ScheduledAction " << this;
2208 ////////////////////// WindowQObject ////////////////////////
2210 WindowQObject::WindowQObject(Window *w)
2211 : parent(w)
2213 //kDebug(6070) << "WindowQObject::WindowQObject " << this;
2214 if ( !parent->m_frame )
2215 kDebug(6070) << "WARNING: null part in " ;
2216 else
2217 connect( parent->m_frame, SIGNAL( destroyed() ),
2218 this, SLOT( parentDestroyed() ) );
2219 pauseLevel = 0;
2220 lastTimerId = 0;
2221 currentlyDispatching = false;
2224 WindowQObject::~WindowQObject()
2226 //kDebug(6070) << "WindowQObject::~WindowQObject " << this;
2227 parentDestroyed(); // reuse same code
2230 void WindowQObject::parentDestroyed()
2232 killTimers();
2234 while (!scheduledActions.isEmpty())
2235 delete scheduledActions.takeFirst();
2236 scheduledActions.clear();
2239 void WindowQObject::pauseTimers()
2241 ++pauseLevel;
2242 if (pauseLevel == 1)
2243 pauseStart = DateTimeMS::now();
2246 void WindowQObject::resumeTimers()
2248 --pauseLevel;
2249 if (pauseLevel == 0) {
2250 // Adjust all timers by the delay length, making sure there is a minimum
2251 // margin from current time, however, so we don't go stampeding off if
2252 // there is some unwanted recursion, etc.
2253 DateTimeMS curTime = DateTimeMS::now();
2254 DateTimeMS earliestDispatch = curTime.addMSecs(5);
2255 int delay = pauseStart.msecsTo(curTime);
2256 foreach (ScheduledAction *action, scheduledActions) {
2257 action->nextTime = action->nextTime.addMSecs(delay);
2258 if (earliestDispatch > action->nextTime)
2259 action->nextTime = earliestDispatch;
2262 // Dispatch any timers that may have been ignored if ::timerEvent fell in the middle
2263 // of a pause..
2264 timerEvent(0);
2268 int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot)
2270 int id = ++lastTimerId;
2271 if (t < 10) t = 10;
2272 DateTimeMS nextTime = DateTimeMS::now().addMSecs(t);
2274 ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id);
2275 scheduledActions.append(action);
2276 setNextTimer();
2277 return id;
2280 int WindowQObject::installTimeout(JSValue *func, List args, int t, bool singleShot)
2282 JSObject *objFunc = func->getObject();
2283 if (!objFunc)
2284 return 0;
2285 int id = ++lastTimerId;
2286 if (t < 10) t = 10;
2288 DateTimeMS nextTime = DateTimeMS::now().addMSecs(t);
2289 ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id);
2290 scheduledActions.append(action);
2291 setNextTimer();
2292 return id;
2295 void WindowQObject::clearTimeout(int timerId)
2297 foreach (ScheduledAction *action, scheduledActions)
2299 if (action->timerId == timerId)
2301 scheduledActions.removeAll(action);
2302 if (!action->executing)
2303 delete action;
2304 return;
2309 bool WindowQObject::hasTimers() const
2311 return scheduledActions.count();
2314 void WindowQObject::mark()
2316 foreach (ScheduledAction *action, scheduledActions)
2318 action->mark();
2322 void WindowQObject::timerEvent(QTimerEvent *)
2324 killTimers();
2326 if (scheduledActions.isEmpty())
2327 return;
2329 if (pauseLevel)
2330 return;
2332 currentlyDispatching = true;
2335 DateTimeMS current = DateTimeMS::now();
2337 // Work out which actions are to be executed. We take a separate copy of
2338 // this list since the main one may be modified during action execution
2339 QList<ScheduledAction*> toExecute;
2340 foreach (ScheduledAction *action, scheduledActions)
2342 if (current >= action->nextTime)
2343 toExecute.append(action);
2346 // ### verify that the window can't be closed (and action deleted) during execution
2347 foreach (ScheduledAction *action, toExecute)
2349 if (!scheduledActions.count(action)) // removed by clearTimeout()
2350 continue;
2352 action->executing = true; // prevent deletion in clearTimeout()
2354 if (parent->part()) {
2355 bool ok = action->execute(parent);
2356 if ( !ok ) // e.g. JS disabled
2357 scheduledActions.removeAll( action );
2360 if (action->singleShot)
2361 scheduledActions.removeAll(action);
2363 action->executing = false;
2365 if (!scheduledActions.count(action))
2366 delete action;
2367 else
2368 action->nextTime = action->nextTime.addMSecs(action->interval);
2371 currentlyDispatching = false;
2373 // Work out when next event is to occur
2374 setNextTimer();
2377 DateTimeMS DateTimeMS::addMSecs(int s) const
2379 DateTimeMS c = *this;
2380 c.mTime = mTime.addMSecs(s);
2381 if (s > 0)
2383 if (c.mTime < mTime)
2384 c.mDate = mDate.addDays(1);
2386 else
2388 if (c.mTime > mTime)
2389 c.mDate = mDate.addDays(-1);
2391 return c;
2394 bool DateTimeMS::operator >(const DateTimeMS &other) const
2396 if (mDate > other.mDate)
2397 return true;
2399 if (mDate < other.mDate)
2400 return false;
2402 return mTime > other.mTime;
2405 bool DateTimeMS::operator >=(const DateTimeMS &other) const
2407 if (mDate > other.mDate)
2408 return true;
2410 if (mDate < other.mDate)
2411 return false;
2413 return mTime >= other.mTime;
2416 int DateTimeMS::msecsTo(const DateTimeMS &other) const
2418 int d = mDate.daysTo(other.mDate);
2419 int ms = mTime.msecsTo(other.mTime);
2420 return d*24*60*60*1000 + ms;
2424 DateTimeMS DateTimeMS::now()
2426 DateTimeMS t;
2427 QTime before = QTime::currentTime();
2428 t.mDate = QDate::currentDate();
2429 t.mTime = QTime::currentTime();
2430 if (t.mTime < before)
2431 t.mDate = QDate::currentDate(); // prevent race condition in hacky way :)
2432 return t;
2435 void WindowQObject::setNextTimer()
2437 if (currentlyDispatching)
2438 return; // Will schedule at the end
2440 if (scheduledActions.isEmpty())
2441 return;
2443 QListIterator<ScheduledAction*> it(scheduledActions);
2444 DateTimeMS nextTime = it.next()->nextTime;
2445 while (it.hasNext())
2447 const DateTimeMS& currTime = it.next()->nextTime;
2448 if (nextTime > currTime)
2449 nextTime = currTime;
2453 int nextInterval = DateTimeMS::now().msecsTo(nextTime);
2454 if (nextInterval < 0)
2455 nextInterval = 0;
2456 timerIds.append(startTimer(nextInterval));
2459 void WindowQObject::killTimers()
2461 for (int i = 0; i < timerIds.size(); ++i)
2463 killTimer(timerIds.at(i));
2465 timerIds.clear();
2468 void WindowQObject::timeoutClose()
2470 parent->closeNow();
2473 ////////////////////// Location Object ////////////////////////
2475 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
2477 @begin LocationTable 11
2478 hash Location::Hash DontDelete
2479 host Location::Host DontDelete
2480 hostname Location::Hostname DontDelete
2481 href Location::Href DontDelete
2482 pathname Location::Pathname DontDelete
2483 port Location::Port DontDelete
2484 protocol Location::Protocol DontDelete
2485 search Location::Search DontDelete
2486 [[==]] Location::EqualEqual DontDelete|ReadOnly
2487 assign Location::Assign DontDelete|Function 1
2488 toString Location::ToString DontDelete|Function 0
2489 replace Location::Replace DontDelete|Function 1
2490 reload Location::Reload DontDelete|Function 0
2491 @end
2493 KJS_IMPLEMENT_PROTOFUNC(LocationFunc)
2494 Location::Location(khtml::ChildFrame *f) : m_frame(f)
2496 //kDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part;
2499 Location::~Location()
2501 //kDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part;
2504 KParts::ReadOnlyPart *Location::part() const {
2505 return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : 0L;
2508 bool Location::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& slot)
2510 #ifdef KJS_VERBOSE
2511 kDebug(6070) << "Location::getOwnPropertySlot " << p.qstring() << " m_part=" << (void*)m_frame->m_part;
2512 #endif
2514 if (m_frame.isNull() || m_frame->m_part.isNull())
2515 return jsUndefined();
2517 const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2519 if ( entry ) {
2520 // properties that work on all Location objects
2521 if (entry->value == Replace) {
2522 getSlotFromEntry<LocationFunc, Location>(entry, this, slot);
2523 return true;
2526 // XSS check
2527 const Window* window = Window::retrieveWindow( m_frame->m_part );
2528 if ( !window || !window->isSafeScript(exec) ) {
2529 slot.setUndefined(this);
2530 return true;
2533 // XSS check passed - can now dispatch normally.
2534 getSlotFromEntry<LocationFunc, Location>(entry, this, slot);
2535 return true;
2538 return JSObject::getOwnPropertySlot(exec, p, slot);
2541 JSValue* Location::getValueProperty(ExecState *exec, int token) const
2543 KUrl url = m_frame->m_part->url();
2544 switch(token) {
2545 case Hash:
2546 return jsString( UString(url.htmlRef().isNull() ? QString("") : '#' + url.htmlRef()) );
2547 case Host: {
2548 UString str = url.host();
2549 if (url.port() > 0)
2550 str = str + QString(":") + QString::number((int)url.port());
2551 return jsString(str);
2552 // Note: this is the IE spec. The NS spec swaps the two, it says
2553 // "The hostname property is the concatenation of the host and port properties, separated by a colon."
2554 // Bleh.
2556 case Hostname:
2557 return jsString( UString(url.host()) );
2558 case Href:
2559 if (url.isEmpty())
2560 return jsString("about:blank");
2561 else if (!url.hasPath())
2562 return jsString( UString(url.prettyUrl()+'/') );
2563 else
2564 return jsString( UString(url.prettyUrl()) );
2565 case Pathname:
2566 if (url.isEmpty())
2567 return jsString("");
2568 return jsString( UString(url.path().isEmpty() ? QString("/") : url.path()) );
2569 case Port:
2570 return jsString( UString(url.port() > 0 ? QString::number((int)url.port()) : QLatin1String("")) );
2571 case Protocol:
2572 return jsString( UString(url.protocol()+':') );
2573 case Search:
2574 return jsString( UString(url.query()) );
2575 case EqualEqual: // [[==]]
2576 return jsString(toString(exec));
2578 return jsUndefined();
2581 void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr)
2583 #ifdef KJS_VERBOSE
2584 kDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part;
2585 #endif
2586 if (m_frame.isNull() || m_frame->m_part.isNull())
2587 return;
2589 const Window* window = Window::retrieveWindow( m_frame->m_part );
2590 if ( !window )
2591 return;
2593 KUrl url = m_frame->m_part->url();
2595 const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
2597 if (entry) {
2599 // XSS check. Only new hrefs can be set from other sites
2600 if (entry->value != Href && !window->isSafeScript(exec))
2601 return;
2603 QString str = v->toString(exec).qstring();
2604 switch (entry->value) {
2605 case Href: {
2606 KHTMLPart* p =qobject_cast<KHTMLPart*>(Window::retrieveActive(exec)->part());
2607 if ( p )
2608 url = p->htmlDocument().completeURL( str ).string();
2609 else
2610 url = str;
2611 break;
2613 case Hash:
2614 // Strip any leading # --- setting hash to #foo is the same as setting it to foo.
2615 if (str.startsWith(QLatin1Char('#')))
2616 str = str.mid(1);
2618 // Note that we want to do gotoAnchor even when the hash is already set, so we
2619 // scroll the destination into view
2620 url.setRef(str);
2621 break;
2622 case Host: {
2623 QString host = str.left(str.indexOf(":"));
2624 QString port = str.mid(str.indexOf(":")+1);
2625 url.setHost(host);
2626 url.setPort(port.toUInt());
2627 break;
2629 case Hostname:
2630 url.setHost(str);
2631 break;
2632 case Pathname:
2633 url.setPath(str);
2634 break;
2635 case Port:
2636 url.setPort(str.toUInt());
2637 break;
2638 case Protocol:
2639 url.setProtocol(str);
2640 break;
2641 case Search:
2642 url.setQuery(str);
2643 break;
2645 } else {
2646 JSObject::put(exec, p, v, attr);
2647 return;
2650 Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
2653 JSValue *Location::toPrimitive(ExecState *exec, JSType) const
2655 if (m_frame) {
2656 Window* window = Window::retrieveWindow( m_frame->m_part );
2657 if ( window && window->isSafeScript(exec) )
2658 return jsString(toString(exec));
2660 return jsUndefined();
2663 UString Location::toString(ExecState *exec) const
2665 if (m_frame) {
2666 Window* window = Window::retrieveWindow( m_frame->m_part );
2667 if ( window && window->isSafeScript(exec) )
2669 KUrl url = m_frame->m_part->url();
2670 if (url.isEmpty())
2671 return "about:blank";
2672 else if (!url.hasPath())
2673 return url.prettyUrl()+'/';
2674 else
2675 return url.prettyUrl();
2678 return "";
2681 JSValue *LocationFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
2683 KJS_CHECK_THIS( Location, thisObj );
2684 Location *location = static_cast<Location *>(thisObj);
2685 KParts::ReadOnlyPart *part = location->part();
2687 if (!part) return jsUndefined();
2689 Window* window = Window::retrieveWindow(part);
2691 if ( !window->isSafeScript(exec) && id != Location::Replace)
2692 return jsUndefined();
2694 switch (id) {
2695 case Location::Assign:
2696 case Location::Replace:
2697 Window::retrieveWindow(part)->goURL(exec, args[0]->toString(exec).qstring(),
2698 id == Location::Replace);
2699 break;
2700 case Location::Reload: {
2701 KHTMLPart *khtmlpart = qobject_cast<KHTMLPart*>(part);
2702 if (khtmlpart)
2703 khtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
2704 else
2705 part->openUrl(part->url());
2706 break;
2708 case Location::ToString:
2709 return jsString(location->toString(exec));
2711 return jsUndefined();
2714 ////////////////////// External Object ////////////////////////
2716 const ClassInfo External::info = { "External", 0, 0, 0 };
2718 @begin ExternalTable 4
2719 addFavorite External::AddFavorite DontDelete|Function 1
2720 @end
2722 KJS_IMPLEMENT_PROTOFUNC(ExternalFunc)
2724 bool External::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& propertySlot)
2726 return getStaticFunctionSlot<ExternalFunc,JSObject>(exec, &ExternalTable, this, p, propertySlot);
2729 JSValue *ExternalFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
2731 KJS_CHECK_THIS( External, thisObj );
2732 External *external = static_cast<External *>(thisObj);
2734 KHTMLPart *part = external->part;
2735 if (!part)
2736 return jsUndefined();
2738 KHTMLView *widget = part->view();
2740 switch (id) {
2741 case External::AddFavorite:
2743 #ifndef KONQ_EMBEDDED
2744 if (!widget->dialogsAllowed())
2745 return jsUndefined();
2746 part->xmlDocImpl()->updateRendering();
2747 if (args.size() != 1 && args.size() != 2)
2748 return jsUndefined();
2750 QString url = args[0]->toString(exec).qstring();
2751 QString title;
2752 if (args.size() == 2)
2753 title = args[1]->toString(exec).qstring();
2755 // AK - don't do anything yet, for the moment i
2756 // just wanted the base js handling code in cvs
2757 return jsUndefined();
2759 QString question;
2760 if ( title.isEmpty() )
2761 question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?",
2762 url);
2763 else
2764 question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?",
2765 url, title);
2767 emit part->browserExtension()->requestFocus(part);
2769 QString caption;
2770 if (!part->url().host().isEmpty())
2771 caption = part->url().host() + " - ";
2772 caption += i18n("JavaScript Attempted Bookmark Insert");
2774 if (KMessageBox::warningYesNo(
2775 widget, question, caption,
2776 KGuiItem(i18n("Insert")), KGuiItem(i18n("Disallow"))) == KMessageBox::Yes)
2778 KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
2779 KBookmarkDialog dlg(mgr, 0);
2780 dlg.addBookmark(title, url);
2782 #else
2783 return jsUndefined();
2784 #endif
2785 break;
2787 default:
2788 return jsUndefined();
2791 return jsUndefined();
2794 ////////////////////// History Object ////////////////////////
2796 const ClassInfo History::info = { "History", 0, 0, 0 };
2798 @begin HistoryTable 4
2799 length History::Length DontDelete|ReadOnly
2800 back History::Back DontDelete|Function 0
2801 forward History::Forward DontDelete|Function 0
2802 go History::Go DontDelete|Function 1
2803 @end
2805 KJS_IMPLEMENT_PROTOFUNC(HistoryFunc)
2807 bool History::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot& slot)
2809 return getStaticPropertySlot<HistoryFunc,History,JSObject>(exec, &HistoryTable, this, p, slot);
2812 JSValue *History::getValueProperty(ExecState *, int token) const
2814 // if previous or next is implemented, make sure its not a major
2815 // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/)
2816 switch (token) {
2817 case Length:
2819 if ( !part )
2820 return jsNumber( 0 );
2822 KParts::BrowserExtension *ext = part->browserExtension();
2823 if ( !ext )
2824 return jsNumber( 0 );
2826 KParts::BrowserInterface *iface = ext->browserInterface();
2827 if ( !iface )
2828 return jsNumber( 0 );
2830 QVariant length = iface->property( "historyLength" );
2832 if ( length.type() != QVariant::UInt )
2833 return jsNumber( 0 );
2835 return jsNumber( length.toUInt() );
2837 default:
2838 kDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token;
2839 return jsUndefined();
2843 JSValue *HistoryFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args)
2845 KJS_CHECK_THIS( History, thisObj );
2846 History *history = static_cast<History *>(thisObj);
2848 JSValue *v = args[0];
2849 double n = 0.0;
2850 if(v)
2851 n = v->toInteger(exec);
2853 int steps;
2854 switch (id) {
2855 case History::Back:
2856 steps = -1;
2857 break;
2858 case History::Forward:
2859 steps = 1;
2860 break;
2861 case History::Go:
2862 steps = (int)n;
2863 break;
2864 default:
2865 return jsUndefined();
2868 // Special case for go(0) from a frame -> reload only the frame
2869 // go(i!=0) from a frame navigates into the history of the frame only,
2870 // in both IE and NS (but not in Mozilla).... we can't easily do that
2871 // in Konqueror...
2872 if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
2874 history->part->openUrl( history->part->url() ); /// ## need args.reload=true?
2875 } else
2877 // Delay it.
2878 // Testcase: history.back(); alert("hello");
2879 Window* window = Window::retrieveWindow( history->part );
2880 window->delayedGoHistory( steps );
2882 return jsUndefined();
2885 } // namespace KJS
2888 #include "kjs_window.moc"