summaryrefslogtreecommitdiffstats
path: root/khtml/ecma/kjs_window.cpp
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce4a32fe52ef09d8f5ff1dd22c001110902b60a2 (patch)
tree5ac38a06f3dde268dc7927dc155896926aaf7012 /khtml/ecma/kjs_window.cpp
downloadtdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.tar.gz
tdelibs-ce4a32fe52ef09d8f5ff1dd22c001110902b60a2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdelibs@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'khtml/ecma/kjs_window.cpp')
-rw-r--r--khtml/ecma/kjs_window.cpp2935
1 files changed, 2935 insertions, 0 deletions
diff --git a/khtml/ecma/kjs_window.cpp b/khtml/ecma/kjs_window.cpp
new file mode 100644
index 000000000..bc5a85e19
--- /dev/null
+++ b/khtml/ecma/kjs_window.cpp
@@ -0,0 +1,2935 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2000-2003 Harri Porten ([email protected])
+ * Copyright (C) 2001-2003 David Faure ([email protected])
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "config.h"
+
+#include "khtmlview.h"
+#include "khtml_part.h"
+#include "khtmlpart_p.h"
+#include "khtml_settings.h"
+#include "xml/dom2_eventsimpl.h"
+#include "xml/dom_docimpl.h"
+#include "misc/htmltags.h"
+#include "html/html_documentimpl.h"
+#include "rendering/render_frames.h"
+
+#include <qstylesheet.h>
+#include <qtimer.h>
+#include <qpaintdevicemetrics.h>
+#include <qapplication.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmdcodec.h>
+#include <kparts/browserinterface.h>
+#include <kwin.h>
+
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+#include <kwinmodule.h> // schroder
+#endif
+
+#ifndef KONQ_EMBEDDED
+#include <kbookmarkmanager.h>
+#endif
+#include <kglobalsettings.h>
+#include <assert.h>
+#include <qstyle.h>
+#include <qobjectlist.h>
+#include <kstringhandler.h>
+
+#include "kjs_proxy.h"
+#include "kjs_window.h"
+#include "kjs_navigator.h"
+#include "kjs_mozilla.h"
+#include "kjs_html.h"
+#include "kjs_range.h"
+#include "kjs_traversal.h"
+#include "kjs_css.h"
+#include "kjs_events.h"
+#include "kjs_views.h"
+#include "xmlhttprequest.h"
+#include "xmlserializer.h"
+#include "domparser.h"
+
+using namespace KJS;
+
+namespace KJS {
+
+ class History : public ObjectImp {
+ friend class HistoryFunc;
+ public:
+ History(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value getValueProperty(ExecState *exec, int token) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { Back, Forward, Go, Length };
+ private:
+ QGuardedPtr<KHTMLPart> part;
+ };
+
+ class External : public ObjectImp {
+ friend class ExternalFunc;
+ public:
+ External(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual const ClassInfo* classInfo() const { return &info; }
+ static const ClassInfo info;
+ enum { AddFavorite };
+ private:
+ QGuardedPtr<KHTMLPart> part;
+ };
+
+ class FrameArray : public ObjectImp {
+ public:
+ FrameArray(ExecState *exec, KHTMLPart *p)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { }
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value call(ExecState *exec, Object &thisObj, const List &args);
+ virtual bool implementsCall() const { return true; }
+ private:
+ QGuardedPtr<KHTMLPart> part;
+ };
+
+#ifdef Q_WS_QWS
+ class KonquerorFunc : public DOMFunction {
+ public:
+ KonquerorFunc(ExecState *exec, const Konqueror* k, const char* name)
+ : DOMFunction(exec), konqueror(k), m_name(name) { }
+ virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args);
+
+ private:
+ const Konqueror* konqueror;
+ QCString m_name;
+ };
+#endif
+} // namespace KJS
+
+#include "kjs_window.lut.h"
+#include "rendering/render_replaced.h"
+
+////////////////////// Screen Object ////////////////////////
+namespace KJS {
+// table for screen object
+/*
+@begin ScreenTable 7
+ height Screen::Height DontEnum|ReadOnly
+ width Screen::Width DontEnum|ReadOnly
+ colorDepth Screen::ColorDepth DontEnum|ReadOnly
+ pixelDepth Screen::PixelDepth DontEnum|ReadOnly
+ availLeft Screen::AvailLeft DontEnum|ReadOnly
+ availTop Screen::AvailTop DontEnum|ReadOnly
+ availHeight Screen::AvailHeight DontEnum|ReadOnly
+ availWidth Screen::AvailWidth DontEnum|ReadOnly
+@end
+*/
+
+const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 };
+
+// We set the object prototype so that toString is implemented
+Screen::Screen(ExecState *exec)
+ : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {}
+
+Value Screen::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Screen::get " << p.qstring() << endl;
+#endif
+ return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this);
+}
+
+Value Screen::getValueProperty(ExecState *exec, int token) const
+{
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ KWinModule info(0, KWinModule::INFO_DESKTOP);
+#endif
+ QWidget *thisWidget = Window::retrieveActive(exec)->part()->widget();
+ QRect sg = KGlobalSettings::desktopGeometry(thisWidget);
+
+ switch( token ) {
+ case Height:
+ return Number(sg.height());
+ case Width:
+ return Number(sg.width());
+ case ColorDepth:
+ case PixelDepth: {
+ QPaintDeviceMetrics m(QApplication::desktop());
+ return Number(m.depth());
+ }
+ case AvailLeft: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ QRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.x()-sg.x());
+#else
+ return Number(10);
+#endif
+ }
+ case AvailTop: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ QRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.y()-sg.y());
+#else
+ return Number(10);
+#endif
+ }
+ case AvailHeight: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ QRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.height());
+#else
+ return Number(100);
+#endif
+ }
+ case AvailWidth: {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ QRect clipped = info.workArea().intersect(sg);
+ return Number(clipped.width());
+#else
+ return Number(100);
+#endif
+ }
+ default:
+ kdDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token << endl;
+ return Undefined();
+ }
+}
+
+////////////////////// Window Object ////////////////////////
+
+const ClassInfo Window::info = { "Window", &DOMAbstractView::info, &WindowTable, 0 };
+
+/*
+@begin WindowTable 162
+ atob Window::AToB DontDelete|Function 1
+ btoa Window::BToA DontDelete|Function 1
+ closed Window::Closed DontDelete|ReadOnly
+ crypto Window::Crypto DontDelete|ReadOnly
+ defaultStatus Window::DefaultStatus DontDelete
+ defaultstatus Window::DefaultStatus DontDelete
+ status Window::Status DontDelete
+ document Window::Document DontDelete|ReadOnly
+ frameElement Window::FrameElement DontDelete|ReadOnly
+ frames Window::Frames DontDelete|ReadOnly
+ history Window::_History DontDelete|ReadOnly
+ external Window::_External DontDelete|ReadOnly
+ event Window::Event DontDelete|ReadOnly
+ innerHeight Window::InnerHeight DontDelete|ReadOnly
+ innerWidth Window::InnerWidth DontDelete|ReadOnly
+ length Window::Length DontDelete|ReadOnly
+ location Window::_Location DontDelete
+ name Window::Name DontDelete
+ navigator Window::_Navigator DontDelete|ReadOnly
+ clientInformation Window::ClientInformation DontDelete|ReadOnly
+ konqueror Window::_Konqueror DontDelete|ReadOnly
+ offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly
+ opener Window::Opener DontDelete|ReadOnly
+ outerHeight Window::OuterHeight DontDelete|ReadOnly
+ outerWidth Window::OuterWidth DontDelete|ReadOnly
+ pageXOffset Window::PageXOffset DontDelete|ReadOnly
+ pageYOffset Window::PageYOffset DontDelete|ReadOnly
+ parent Window::Parent DontDelete|ReadOnly
+ personalbar Window::Personalbar DontDelete|ReadOnly
+ screenX Window::ScreenX DontDelete|ReadOnly
+ screenY Window::ScreenY DontDelete|ReadOnly
+ scrollbars Window::Scrollbars DontDelete|ReadOnly
+ scroll Window::Scroll DontDelete|Function 2
+ scrollBy Window::ScrollBy DontDelete|Function 2
+ scrollTo Window::ScrollTo DontDelete|Function 2
+ scrollX Window::ScrollX DontDelete|ReadOnly
+ scrollY Window::ScrollY DontDelete|ReadOnly
+ moveBy Window::MoveBy DontDelete|Function 2
+ moveTo Window::MoveTo DontDelete|Function 2
+ resizeBy Window::ResizeBy DontDelete|Function 2
+ resizeTo Window::ResizeTo DontDelete|Function 2
+ self Window::Self DontDelete|ReadOnly
+ window Window::_Window DontDelete|ReadOnly
+ top Window::Top DontDelete|ReadOnly
+ screen Window::_Screen DontDelete|ReadOnly
+ alert Window::Alert DontDelete|Function 1
+ confirm Window::Confirm DontDelete|Function 1
+ prompt Window::Prompt DontDelete|Function 2
+ open Window::Open DontDelete|Function 3
+ setTimeout Window::SetTimeout DontDelete|Function 2
+ clearTimeout Window::ClearTimeout DontDelete|Function 1
+ focus Window::Focus DontDelete|Function 0
+ blur Window::Blur DontDelete|Function 0
+ close Window::Close DontDelete|Function 0
+ setInterval Window::SetInterval DontDelete|Function 2
+ clearInterval Window::ClearInterval DontDelete|Function 1
+ captureEvents Window::CaptureEvents DontDelete|Function 0
+ releaseEvents Window::ReleaseEvents DontDelete|Function 0
+ print Window::Print DontDelete|Function 0
+ addEventListener Window::AddEventListener DontDelete|Function 3
+ removeEventListener Window::RemoveEventListener DontDelete|Function 3
+# Normally found in prototype. Add to window object itself to make them
+# accessible in closed and cross-site windows
+ valueOf Window::ValueOf DontDelete|Function 0
+ toString Window::ToString DontDelete|Function 0
+# IE extension
+ navigate Window::Navigate DontDelete|Function 1
+# Mozilla extension
+ sidebar Window::SideBar DontDelete|ReadOnly
+ getComputedStyle Window::GetComputedStyle DontDelete|Function 2
+
+# Warning, when adding a function to this object you need to add a case in Window::get
+
+# Event handlers
+# IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect,
+# ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll.
+# It doesn't have onabort, onchange, ondragdrop (but NS has that last one).
+ onabort Window::Onabort DontDelete
+ onblur Window::Onblur DontDelete
+ onchange Window::Onchange DontDelete
+ onclick Window::Onclick DontDelete
+ ondblclick Window::Ondblclick DontDelete
+ ondragdrop Window::Ondragdrop DontDelete
+ onerror Window::Onerror DontDelete
+ onfocus Window::Onfocus DontDelete
+ onkeydown Window::Onkeydown DontDelete
+ onkeypress Window::Onkeypress DontDelete
+ onkeyup Window::Onkeyup DontDelete
+ onload Window::Onload DontDelete
+ onmousedown Window::Onmousedown DontDelete
+ onmousemove Window::Onmousemove DontDelete
+ onmouseout Window::Onmouseout DontDelete
+ onmouseover Window::Onmouseover DontDelete
+ onmouseup Window::Onmouseup DontDelete
+ onmove Window::Onmove DontDelete
+ onreset Window::Onreset DontDelete
+ onresize Window::Onresize DontDelete
+ onselect Window::Onselect DontDelete
+ onsubmit Window::Onsubmit DontDelete
+ onunload Window::Onunload DontDelete
+
+# Constructors/constant tables
+ Node Window::Node DontDelete
+ Event Window::EventCtor DontDelete
+ Range Window::Range DontDelete
+ NodeFilter Window::NodeFilter DontDelete
+ DOMException Window::DOMException DontDelete
+ CSSRule Window::CSSRule DontDelete
+ MutationEvent Window::MutationEventCtor DontDelete
+ KeyboardEvent Window::KeyboardEventCtor DontDelete
+ EventException Window::EventExceptionCtor DontDelete
+ Image Window::Image DontDelete|ReadOnly
+ Option Window::Option DontDelete|ReadOnly
+ XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly
+ XMLSerializer Window::XMLSerializer DontDelete|ReadOnly
+ DOMParser Window::DOMParser DontDelete|ReadOnly
+
+# Mozilla dom emulation ones.
+ Element Window::ElementCtor DontDelete
+ Document Window::DocumentCtor DontDelete
+ #this one is an alias since we don't have a separate XMLDocument
+ XMLDocument Window::DocumentCtor DontDelete
+ HTMLElement Window::HTMLElementCtor DontDelete
+ HTMLDocument Window::HTMLDocumentCtor DontDelete
+ HTMLHtmlElement Window::HTMLHtmlElementCtor DontDelete
+ HTMLHeadElement Window::HTMLHeadElementCtor DontDelete
+ HTMLLinkElement Window::HTMLLinkElementCtor DontDelete
+ HTMLTitleElement Window::HTMLTitleElementCtor DontDelete
+ HTMLMetaElement Window::HTMLMetaElementCtor DontDelete
+ HTMLBaseElement Window::HTMLBaseElementCtor DontDelete
+ HTMLIsIndexElement Window::HTMLIsIndexElementCtor DontDelete
+ HTMLStyleElement Window::HTMLStyleElementCtor DontDelete
+ HTMLBodyElement Window::HTMLBodyElementCtor DontDelete
+ HTMLFormElement Window::HTMLFormElementCtor DontDelete
+ HTMLSelectElement Window::HTMLSelectElementCtor DontDelete
+ HTMLOptGroupElement Window::HTMLOptGroupElementCtor DontDelete
+ HTMLOptionElement Window::HTMLOptionElementCtor DontDelete
+ HTMLInputElement Window::HTMLInputElementCtor DontDelete
+ HTMLTextAreaElement Window::HTMLTextAreaElementCtor DontDelete
+ HTMLButtonElement Window::HTMLButtonElementCtor DontDelete
+ HTMLLabelElement Window::HTMLLabelElementCtor DontDelete
+ HTMLFieldSetElement Window::HTMLFieldSetElementCtor DontDelete
+ HTMLLegendElement Window::HTMLLegendElementCtor DontDelete
+ HTMLUListElement Window::HTMLUListElementCtor DontDelete
+ HTMLOListElement Window::HTMLOListElementCtor DontDelete
+ HTMLDListElement Window::HTMLDListElementCtor DontDelete
+ HTMLDirectoryElement Window::HTMLDirectoryElementCtor DontDelete
+ HTMLMenuElement Window::HTMLMenuElementCtor DontDelete
+ HTMLLIElement Window::HTMLLIElementCtor DontDelete
+ HTMLDivElement Window::HTMLDivElementCtor DontDelete
+ HTMLParagraphElement Window::HTMLParagraphElementCtor DontDelete
+ HTMLHeadingElement Window::HTMLHeadingElementCtor DontDelete
+ HTMLBlockQuoteElement Window::HTMLBlockQuoteElementCtor DontDelete
+ HTMLQuoteElement Window::HTMLQuoteElementCtor DontDelete
+ HTMLPreElement Window::HTMLPreElementCtor DontDelete
+ HTMLBRElement Window::HTMLBRElementCtor DontDelete
+ HTMLBaseFontElement Window::HTMLBaseFontElementCtor DontDelete
+ HTMLFontElement Window::HTMLFontElementCtor DontDelete
+ HTMLHRElement Window::HTMLHRElementCtor DontDelete
+ HTMLModElement Window::HTMLModElementCtor DontDelete
+ HTMLAnchorElement Window::HTMLAnchorElementCtor DontDelete
+ HTMLImageElement Window::HTMLImageElementCtor DontDelete
+ HTMLObjectElement Window::HTMLObjectElementCtor DontDelete
+ HTMLParamElement Window::HTMLParamElementCtor DontDelete
+ HTMLAppletElement Window::HTMLAppletElementCtor DontDelete
+ HTMLMapElement Window::HTMLMapElementCtor DontDelete
+ HTMLAreaElement Window::HTMLAreaElementCtor DontDelete
+ HTMLScriptElement Window::HTMLScriptElementCtor DontDelete
+ HTMLTableElement Window::HTMLTableElementCtor DontDelete
+ HTMLTableCaptionElement Window::HTMLTableCaptionElementCtor DontDelete
+ HTMLTableColElement Window::HTMLTableColElementCtor DontDelete
+ HTMLTableSectionElement Window::HTMLTableSectionElementCtor DontDelete
+ HTMLTableRowElement Window::HTMLTableRowElementCtor DontDelete
+ HTMLTableCellElement Window::HTMLTableCellElementCtor DontDelete
+ HTMLFrameSetElement Window::HTMLFrameSetElementCtor DontDelete
+ HTMLLayerElement Window::HTMLLayerElementCtor DontDelete
+ HTMLFrameElement Window::HTMLFrameElementCtor DontDelete
+ HTMLIFrameElement Window::HTMLIFrameElementCtor DontDelete
+ CSSStyleDeclaration Window::CSSStyleDeclarationCtor DontDelete
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(WindowFunc)
+
+Window::Window(khtml::ChildFrame *p)
+ : ObjectImp(/*no proto*/), m_frame(p), screen(0), history(0), external(0), m_frames(0), loc(0), m_evt(0)
+{
+ winq = new WindowQObject(this);
+ //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl;
+}
+
+Window::~Window()
+{
+ delete winq;
+}
+
+Window *Window::retrieveWindow(KParts::ReadOnlyPart *p)
+{
+ Object obj = Object::dynamicCast( retrieve( p ) );
+#ifndef NDEBUG
+ // obj should never be null, except when javascript has been disabled in that part.
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(p);
+ if ( part && part->jScriptEnabled() )
+ {
+ assert( obj.isValid() );
+#ifndef QWS
+ assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking
+#endif
+ }
+#endif
+ if ( !obj.isValid() ) // JS disabled
+ return 0;
+ return static_cast<KJS::Window*>(obj.imp());
+}
+
+Window *Window::retrieveActive(ExecState *exec)
+{
+ ValueImp *imp = exec->interpreter()->globalObject().imp();
+ assert( imp );
+#ifndef QWS
+ assert( dynamic_cast<KJS::Window*>(imp) );
+#endif
+ return static_cast<KJS::Window*>(imp);
+}
+
+Value Window::retrieve(KParts::ReadOnlyPart *p)
+{
+ assert(p);
+ KHTMLPart * part = ::qt_cast<KHTMLPart *>(p);
+ KJSProxy *proxy = 0L;
+ if (!part) {
+ part = ::qt_cast<KHTMLPart *>(p->parent());
+ if (part)
+ proxy = part->framejScript(p);
+ } else
+ proxy = part->jScript();
+ if (proxy) {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window::retrieve part=" << part << " '" << part->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl;
+#endif
+ return proxy->interpreter()->globalObject(); // the Global object is the "window"
+ } else {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl;
+#endif
+ return Undefined(); // This can happen with JS disabled on the domain of that window
+ }
+}
+
+Location *Window::location() const
+{
+ if (!loc)
+ const_cast<Window*>(this)->loc = new Location(m_frame);
+ return loc;
+}
+
+ObjectImp* Window::frames( ExecState* exec ) const
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (part)
+ return m_frames ? m_frames :
+ (const_cast<Window*>(this)->m_frames = new FrameArray(exec, part));
+ return 0L;
+}
+
+// reference our special objects during garbage collection
+void Window::mark()
+{
+ ObjectImp::mark();
+ if (screen && !screen->marked())
+ screen->mark();
+ if (history && !history->marked())
+ history->mark();
+ if (external && !external->marked())
+ external->mark();
+ if (m_frames && !m_frames->marked())
+ m_frames->mark();
+ //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl;
+ if (loc && !loc->marked())
+ loc->mark();
+ if (winq)
+ winq->mark();
+}
+
+bool Window::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ // we don't want any operations on a closed window
+ if (m_frame.isNull() || m_frame->m_part.isNull())
+ return ( p == "closed" );
+
+ if (ObjectImp::hasProperty(exec, p))
+ return true;
+
+ if (Lookup::findEntry(&WindowTable, p))
+ return true;
+
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return false;
+
+ QString q = p.qstring();
+ if (part->findFramePart(p.qstring()))
+ return true;
+ // allow window[1] or parent[1] etc. (#56983)
+ bool ok;
+ unsigned int i = p.toArrayIndex(&ok);
+ if (ok) {
+ QPtrList<KParts::ReadOnlyPart> frames = part->frames();
+ unsigned int len = frames.count();
+ if (i < len)
+ return true;
+ }
+
+ // allow shortcuts like 'Image1' instead of document.images.Image1
+ if (part->document().isHTMLDocument()) { // might be XML
+ DOM::HTMLDocument doc = part->htmlDocument();
+ // Keep in sync with tryGet
+
+ if (static_cast<DOM::DocumentImpl*>(doc.handle())->underDocNamedCache().get(p.qstring()))
+ return true;
+
+ return !doc.getElementById(p.string()).isNull();
+ }
+
+ return false;
+}
+
+UString Window::toString(ExecState *) const
+{
+ return "[object Window]";
+}
+
+Value Window::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl;
+#endif
+ // we want only limited operations on a closed window
+ if (m_frame.isNull() || m_frame->m_part.isNull()) {
+ const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
+ if (entry) {
+ switch (entry->value) {
+ case Closed:
+ return Boolean(true);
+ case _Location:
+ return Null();
+ case ValueOf:
+ case ToString:
+ return lookupOrCreateFunction<WindowFunc>(exec,p, this, entry->value,
+ entry->params, entry->attr);
+ default:
+ break;
+ }
+ }
+ return Undefined();
+ }
+
+ // Look for overrides first
+ ValueImp *val = getDirect(p);
+ if (val) {
+ //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl;
+ return isSafeScript(exec) ? Value(val) : Undefined();
+ }
+
+ const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+
+ // properties that work on all windows
+ if (entry) {
+ // ReadOnlyPart first
+ switch(entry->value) {
+ case Closed:
+ return Boolean( false );
+ case _Location:
+ // No isSafeScript test here, we must be able to _set_ location.href (#49819)
+ return Value(location());
+ case _Window:
+ case Self:
+ return retrieve(m_frame->m_part);
+ default:
+ break;
+ }
+ if (!part)
+ return Undefined();
+ // KHTMLPart next
+ switch(entry->value) {
+ case Frames:
+ return Value(frames(exec));
+ case Opener:
+ if (!part->opener())
+ return Null(); // ### a null Window might be better, but == null
+ else // doesn't work yet
+ return retrieve(part->opener());
+ case Parent:
+ return retrieve(part->parentPart() ? part->parentPart() : (KHTMLPart*)part);
+ case Top: {
+ KHTMLPart *p = part;
+ while (p->parentPart())
+ p = p->parentPart();
+ return retrieve(p);
+ }
+ case Alert:
+ case Confirm:
+ case Prompt:
+ case Open:
+ case Close:
+ case Focus:
+ case Blur:
+ case AToB:
+ case BToA:
+ case GetComputedStyle:
+ case ValueOf:
+ case ToString:
+ return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ default:
+ break;
+ }
+ } else if (!part) {
+ // not a KHTMLPart
+ QString rvalue;
+ KParts::LiveConnectExtension::Type rtype;
+ unsigned long robjid;
+ if (m_frame->m_liveconnect &&
+ isSafeScript(exec) &&
+ m_frame->m_liveconnect->get(0, p.qstring(), rtype, robjid, rvalue))
+ return getLiveConnectValue(m_frame->m_liveconnect, p.qstring(), rtype, rvalue, robjid);
+ return Undefined();
+ }
+ // properties that only work on safe windows
+ if (isSafeScript(exec) && entry)
+ {
+ //kdDebug(6070) << "token: " << entry->value << endl;
+ switch( entry->value ) {
+ case Crypto:
+ return Undefined(); // ###
+ case DefaultStatus:
+ return String(UString(part->jsDefaultStatusBarText()));
+ case Status:
+ return String(UString(part->jsStatusBarText()));
+ case Document:
+ if (part->document().isNull()) {
+ kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl;
+ part->begin();
+ part->write("<HTML><BODY>");
+ part->end();
+ }
+ return getDOMNode(exec,part->document());
+ case FrameElement:
+ if (m_frame->m_frame)
+ return getDOMNode(exec,m_frame->m_frame->element());
+ else
+ return Undefined();
+ case Node:
+ return NodeConstructor::self(exec);
+ case Range:
+ return getRangeConstructor(exec);
+ case NodeFilter:
+ return getNodeFilterConstructor(exec);
+ case DOMException:
+ return getDOMExceptionConstructor(exec);
+ case CSSRule:
+ return getCSSRuleConstructor(exec);
+ case ElementCtor:
+ return ElementPseudoCtor::self(exec);
+ case HTMLElementCtor:
+ return HTMLElementPseudoCtor::self(exec);
+ case HTMLHtmlElementCtor:
+ return HTMLHtmlElementPseudoCtor::self(exec);
+ case HTMLHeadElementCtor:
+ return HTMLHeadElementPseudoCtor::self(exec);
+ case HTMLLinkElementCtor:
+ return HTMLLinkElementPseudoCtor::self(exec);
+ case HTMLTitleElementCtor:
+ return HTMLTitleElementPseudoCtor::self(exec);
+ case HTMLMetaElementCtor:
+ return HTMLMetaElementPseudoCtor::self(exec);
+ case HTMLBaseElementCtor:
+ return HTMLBaseElementPseudoCtor::self(exec);
+ case HTMLIsIndexElementCtor:
+ return HTMLIsIndexElementPseudoCtor::self(exec);
+ case HTMLStyleElementCtor:
+ return HTMLStyleElementPseudoCtor::self(exec);
+ case HTMLBodyElementCtor:
+ return HTMLBodyElementPseudoCtor::self(exec);
+ case HTMLFormElementCtor:
+ return HTMLFormElementPseudoCtor::self(exec);
+ case HTMLSelectElementCtor:
+ return HTMLSelectElementPseudoCtor::self(exec);
+ case HTMLOptGroupElementCtor:
+ return HTMLOptGroupElementPseudoCtor::self(exec);
+ case HTMLOptionElementCtor:
+ return HTMLOptionElementPseudoCtor::self(exec);
+ case HTMLInputElementCtor:
+ return HTMLInputElementPseudoCtor::self(exec);
+ case HTMLTextAreaElementCtor:
+ return HTMLTextAreaElementPseudoCtor::self(exec);
+ case HTMLButtonElementCtor:
+ return HTMLButtonElementPseudoCtor::self(exec);
+ case HTMLLabelElementCtor:
+ return HTMLLabelElementPseudoCtor::self(exec);
+ case HTMLFieldSetElementCtor:
+ return HTMLFieldSetElementPseudoCtor::self(exec);
+ case HTMLLegendElementCtor:
+ return HTMLLegendElementPseudoCtor::self(exec);
+ case HTMLUListElementCtor:
+ return HTMLUListElementPseudoCtor::self(exec);
+ case HTMLOListElementCtor:
+ return HTMLOListElementPseudoCtor::self(exec);
+ case HTMLDListElementCtor:
+ return HTMLDListElementPseudoCtor::self(exec);
+ case HTMLDirectoryElementCtor:
+ return HTMLDirectoryElementPseudoCtor::self(exec);
+ case HTMLMenuElementCtor:
+ return HTMLMenuElementPseudoCtor::self(exec);
+ case HTMLLIElementCtor:
+ return HTMLLIElementPseudoCtor::self(exec);
+ case HTMLDivElementCtor:
+ return HTMLDivElementPseudoCtor::self(exec);
+ case HTMLParagraphElementCtor:
+ return HTMLParagraphElementPseudoCtor::self(exec);
+ case HTMLHeadingElementCtor:
+ return HTMLHeadingElementPseudoCtor::self(exec);
+ case HTMLBlockQuoteElementCtor:
+ return HTMLBlockQuoteElementPseudoCtor::self(exec);
+ case HTMLQuoteElementCtor:
+ return HTMLQuoteElementPseudoCtor::self(exec);
+ case HTMLPreElementCtor:
+ return HTMLPreElementPseudoCtor::self(exec);
+ case HTMLBRElementCtor:
+ return HTMLBRElementPseudoCtor::self(exec);
+ case HTMLBaseFontElementCtor:
+ return HTMLBaseFontElementPseudoCtor::self(exec);
+ case HTMLFontElementCtor:
+ return HTMLFontElementPseudoCtor::self(exec);
+ case HTMLHRElementCtor:
+ return HTMLHRElementPseudoCtor::self(exec);
+ case HTMLModElementCtor:
+ return HTMLModElementPseudoCtor::self(exec);
+ case HTMLAnchorElementCtor:
+ return HTMLAnchorElementPseudoCtor::self(exec);
+ case HTMLImageElementCtor:
+ return HTMLImageElementPseudoCtor::self(exec);
+ case HTMLObjectElementCtor:
+ return HTMLObjectElementPseudoCtor::self(exec);
+ case HTMLParamElementCtor:
+ return HTMLParamElementPseudoCtor::self(exec);
+ case HTMLAppletElementCtor:
+ return HTMLAppletElementPseudoCtor::self(exec);
+ case HTMLMapElementCtor:
+ return HTMLMapElementPseudoCtor::self(exec);
+ case HTMLAreaElementCtor:
+ return HTMLAreaElementPseudoCtor::self(exec);
+ case HTMLScriptElementCtor:
+ return HTMLScriptElementPseudoCtor::self(exec);
+ case HTMLTableElementCtor:
+ return HTMLTableElementPseudoCtor::self(exec);
+ case HTMLTableCaptionElementCtor:
+ return HTMLTableCaptionElementPseudoCtor::self(exec);
+ case HTMLTableColElementCtor:
+ return HTMLTableColElementPseudoCtor::self(exec);
+ case HTMLTableSectionElementCtor:
+ return HTMLTableSectionElementPseudoCtor::self(exec);
+ case HTMLTableRowElementCtor:
+ return HTMLTableRowElementPseudoCtor::self(exec);
+ case HTMLTableCellElementCtor:
+ return HTMLTableCellElementPseudoCtor::self(exec);
+ case HTMLFrameSetElementCtor:
+ return HTMLFrameSetElementPseudoCtor::self(exec);
+ case HTMLLayerElementCtor:
+ return HTMLLayerElementPseudoCtor::self(exec);
+ case HTMLFrameElementCtor:
+ return HTMLFrameElementPseudoCtor::self(exec);
+ case HTMLIFrameElementCtor:
+ return HTMLIFrameElementPseudoCtor::self(exec);
+ case DocumentCtor:
+ return DocumentPseudoCtor::self(exec);
+ case HTMLDocumentCtor:
+ return HTMLDocumentPseudoCtor::self(exec);
+ case CSSStyleDeclarationCtor:
+ return CSSStyleDeclarationPseudoCtor::self(exec);
+ case EventCtor:
+ return EventConstructor::self(exec);
+ case MutationEventCtor:
+ return getMutationEventConstructor(exec);
+ case KeyboardEventCtor:
+ return getKeyboardEventConstructor(exec);
+ case EventExceptionCtor:
+ return getEventExceptionConstructor(exec);
+ case _History:
+ return Value(history ? history :
+ (const_cast<Window*>(this)->history = new History(exec,part)));
+
+ case _External:
+ return Value(external ? external :
+ (const_cast<Window*>(this)->external = new External(exec,part)));
+
+ case Event:
+ if (m_evt)
+ return getDOMEvent(exec,*m_evt);
+ else {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "WARNING: window(" << this << "," << part->name() << ").event, no event!" << endl;
+#endif
+ return Undefined();
+ }
+ case InnerHeight:
+ if (!part->view())
+ return Undefined();
+ khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
+ return Number(part->view()->visibleHeight());
+ case InnerWidth:
+ if (!part->view())
+ return Undefined();
+ khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
+ return Number(part->view()->visibleWidth());
+ case Length:
+ return Number(part->frames().count());
+ case Name:
+ return String(part->name());
+ case SideBar:
+ return Value(new MozillaSidebarExtension(exec, part));
+ case _Navigator:
+ case ClientInformation: {
+ // Store the navigator in the object so we get the same one each time.
+ Value nav( new Navigator(exec, part) );
+ const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal);
+ const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal);
+ return nav;
+ }
+#ifdef Q_WS_QWS
+ case _Konqueror: {
+ Value k( new Konqueror(part) );
+ const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal);
+ return k;
+ }
+#endif
+ case OffscreenBuffering:
+ return Boolean(true);
+ case OuterHeight:
+ case OuterWidth:
+ {
+#if defined Q_WS_X11 && ! defined K_WS_QTONLY
+ if (!part->widget())
+ return Number(0);
+ KWin::WindowInfo inf = KWin::windowInfo(part->widget()->topLevelWidget()->winId());
+ return Number(entry->value == OuterHeight ?
+ inf.geometry().height() : inf.geometry().width());
+#else
+ return Number(entry->value == OuterHeight ?
+ part->view()->height() : part->view()->width());
+#endif
+ }
+ case PageXOffset:
+ return Number(part->view()->contentsX());
+ case PageYOffset:
+ return Number(part->view()->contentsY());
+ case Personalbar:
+ return Undefined(); // ###
+ case ScreenLeft:
+ case ScreenX: {
+ if (!part->view())
+ return Undefined();
+ QRect sg = KGlobalSettings::desktopGeometry(part->view());
+ return Number(part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x());
+ }
+ case ScreenTop:
+ case ScreenY: {
+ if (!part->view())
+ return Undefined();
+ QRect sg = KGlobalSettings::desktopGeometry(part->view());
+ return Number(part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y());
+ }
+ case ScrollX: {
+ if (!part->view())
+ return Undefined();
+ return Number(part->view()->contentsX());
+ }
+ case ScrollY: {
+ if (!part->view())
+ return Undefined();
+ return Number(part->view()->contentsY());
+ }
+ case Scrollbars:
+ return Undefined(); // ###
+ case _Screen:
+ return Value(screen ? screen :
+ (const_cast<Window*>(this)->screen = new Screen(exec)));
+ case Image:
+ return Value(new ImageConstructorImp(exec, part->document()));
+ case Option:
+ return Value(new OptionConstructorImp(exec, part->document()));
+ case XMLHttpRequest:
+ return Value(new XMLHttpRequestConstructorImp(exec, part->document()));
+ case XMLSerializer:
+ return Value(new XMLSerializerConstructorImp(exec));
+ case DOMParser:
+ return Value(new DOMParserConstructorImp(exec, part->xmlDocImpl()));
+ case Scroll: // compatibility
+ case ScrollBy:
+ case ScrollTo:
+ case MoveBy:
+ case MoveTo:
+ case ResizeBy:
+ case ResizeTo:
+ case CaptureEvents:
+ case ReleaseEvents:
+ case AddEventListener:
+ case RemoveEventListener:
+ case SetTimeout:
+ case ClearTimeout:
+ case SetInterval:
+ case ClearInterval:
+ case Print:
+ return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ // IE extension
+ case Navigate:
+ // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses
+ // if (navigate) to test for IE (unlikely).
+ if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat )
+ return Undefined();
+ return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ case Onabort:
+ return getListener(exec,DOM::EventImpl::ABORT_EVENT);
+ case Onblur:
+ return getListener(exec,DOM::EventImpl::BLUR_EVENT);
+ case Onchange:
+ return getListener(exec,DOM::EventImpl::CHANGE_EVENT);
+ case Onclick:
+ return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT);
+ case Ondblclick:
+ return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT);
+ case Ondragdrop:
+ return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT);
+ case Onerror:
+ return getListener(exec,DOM::EventImpl::ERROR_EVENT);
+ case Onfocus:
+ return getListener(exec,DOM::EventImpl::FOCUS_EVENT);
+ case Onkeydown:
+ return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT);
+ case Onkeypress:
+ return getListener(exec,DOM::EventImpl::KEYPRESS_EVENT);
+ case Onkeyup:
+ return getListener(exec,DOM::EventImpl::KEYUP_EVENT);
+ case Onload:
+ return getListener(exec,DOM::EventImpl::LOAD_EVENT);
+ case Onmousedown:
+ return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT);
+ case Onmousemove:
+ return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT);
+ case Onmouseout:
+ return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT);
+ case Onmouseover:
+ return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT);
+ case Onmouseup:
+ return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT);
+ case Onmove:
+ return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT);
+ case Onreset:
+ return getListener(exec,DOM::EventImpl::RESET_EVENT);
+ case Onresize:
+ return getListener(exec,DOM::EventImpl::RESIZE_EVENT);
+ case Onselect:
+ return getListener(exec,DOM::EventImpl::SELECT_EVENT);
+ case Onsubmit:
+ return getListener(exec,DOM::EventImpl::SUBMIT_EVENT);
+ case Onunload:
+ return getListener(exec,DOM::EventImpl::UNLOAD_EVENT);
+ }
+ }
+
+ // doing the remainder of ObjectImp::get() that is not covered by
+ // the getDirect() call above.
+ // #### guessed position. move further up or down?
+ Object proto = Object::dynamicCast(prototype());
+ assert(proto.isValid());
+ if (p == specialPrototypePropertyName)
+ return isSafeScript(exec) ? Value(proto) : Undefined();
+ Value val2 = proto.get(exec, p);
+ if (!val2.isA(UndefinedType)) {
+ return isSafeScript(exec) ? val2 : Undefined();
+ }
+
+ KParts::ReadOnlyPart *rop = part->findFramePart( p.qstring() );
+ if (rop)
+ return retrieve(rop);
+
+ // allow window[1] or parent[1] etc. (#56983)
+ bool ok;
+ unsigned int i = p.toArrayIndex(&ok);
+ if (ok) {
+ QPtrList<KParts::ReadOnlyPart> frames = part->frames();
+ unsigned int len = frames.count();
+ if (i < len) {
+ KParts::ReadOnlyPart* frame = frames.at(i);
+ if (frame)
+ return Window::retrieve(frame);
+ }
+ }
+
+ //Check for images, forms, objects, etc.
+ if (isSafeScript(exec) && part->document().isHTMLDocument()) { // might be XML
+ DOM::DocumentImpl* docImpl = part->xmlDocImpl();
+ DOM::ElementMappingCache::ItemInfo* info = docImpl->underDocNamedCache().get(p.qstring());
+ if (info) {
+ //May be a false positive, but we can try to avoid doing it the hard way in
+ //simpler cases. The trickiness here is that the cache is kept under both
+ //name and id, but we sometimes ignore id for IE compat
+ DOM::DOMString propertyDOMString = p.string();
+ if (info->nd && DOM::HTMLMappedNameCollectionImpl::matchesName(info->nd,
+ DOM::HTMLCollectionImpl::WINDOW_NAMED_ITEMS, propertyDOMString)) {
+ return getDOMNode(exec, info->nd);
+ } else {
+ //Can't tell it just like that, so better go through collection and count stuff. This is the slow path...
+ DOM::HTMLMappedNameCollection coll(docImpl, DOM::HTMLCollectionImpl::WINDOW_NAMED_ITEMS, propertyDOMString);
+
+ if (coll.length() == 1)
+ return getDOMNode(exec, coll.firstItem());
+ else if (coll.length() > 1)
+ return getHTMLCollection(exec, coll);
+ }
+ }
+ DOM::Element element = part->document().getElementById(p.string());
+ if ( !element.isNull() )
+ return getDOMNode(exec, element );
+ }
+
+ // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1
+ // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping.
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl;
+#endif
+ return Undefined();
+}
+
+void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr)
+{
+ // we don't want any operations on a closed window
+ if (m_frame.isNull() || m_frame->m_part.isNull()) {
+ // ### throw exception? allow setting of some props like location?
+ return;
+ }
+
+ // Called by an internal KJS call (e.g. InterpreterImp's constructor) ?
+ // If yes, save time and jump directly to ObjectImp.
+ if ( (attr != None && attr != DontDelete) ||
+ // Same thing if we have a local override (e.g. "var location")
+ ( isSafeScript( exec ) && ObjectImp::getDirect(propertyName) ) )
+ {
+ ObjectImp::put( exec, propertyName, value, attr );
+ return;
+ }
+
+ const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);
+ if (entry && !m_frame.isNull() && !m_frame->m_part.isNull())
+ {
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl;
+#endif
+ switch( entry->value) {
+ case _Location:
+ goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/);
+ return;
+ default:
+ break;
+ }
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (part) {
+ switch( entry->value ) {
+ case Status: {
+ if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
+ == KHTMLSettings::KJSWindowStatusAllow) {
+ String s = value.toString(exec);
+ part->setJSStatusBarText(s.value().qstring());
+ }
+ return;
+ }
+ case DefaultStatus: {
+ if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host())
+ == KHTMLSettings::KJSWindowStatusAllow) {
+ String s = value.toString(exec);
+ part->setJSDefaultStatusBarText(s.value().qstring());
+ }
+ return;
+ }
+ case Onabort:
+ if (isSafeScript(exec))
+ setListener(exec, DOM::EventImpl::ABORT_EVENT,value);
+ return;
+ case Onblur:
+ if (isSafeScript(exec))
+ setListener(exec, DOM::EventImpl::BLUR_EVENT,value);
+ return;
+ case Onchange:
+ if (isSafeScript(exec))
+ setListener(exec, DOM::EventImpl::CHANGE_EVENT,value);
+ return;
+ case Onclick:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value);
+ return;
+ case Ondblclick:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value);
+ return;
+ case Ondragdrop:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value);
+ return;
+ case Onerror:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::ERROR_EVENT,value);
+ return;
+ case Onfocus:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::FOCUS_EVENT,value);
+ return;
+ case Onkeydown:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value);
+ return;
+ case Onkeypress:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KEYPRESS_EVENT,value);
+ return;
+ case Onkeyup:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KEYUP_EVENT,value);
+ return;
+ case Onload:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::LOAD_EVENT,value);
+ return;
+ case Onmousedown:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value);
+ return;
+ case Onmousemove:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value);
+ return;
+ case Onmouseout:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value);
+ return;
+ case Onmouseover:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value);
+ return;
+ case Onmouseup:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value);
+ return;
+ case Onmove:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value);
+ return;
+ case Onreset:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::RESET_EVENT,value);
+ return;
+ case Onresize:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::RESIZE_EVENT,value);
+ return;
+ case Onselect:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::SELECT_EVENT,value);
+ return;
+ case Onsubmit:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value);
+ return;
+ case Onunload:
+ if (isSafeScript(exec))
+ setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value);
+ return;
+ case Name:
+ if (isSafeScript(exec))
+ part->setName( value.toString(exec).qstring().local8Bit().data() );
+ return;
+ default:
+ break;
+ }
+ }
+ }
+ if (m_frame->m_liveconnect &&
+ isSafeScript(exec) &&
+ m_frame->m_liveconnect->put(0, propertyName.qstring(), value.toString(exec).qstring()))
+ return;
+ if (isSafeScript(exec)) {
+ //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl;
+ ObjectImp::put(exec, propertyName, value, attr);
+ }
+}
+
+bool Window::toBoolean(ExecState *) const
+{
+ return !m_frame.isNull() && !m_frame->m_part.isNull();
+}
+
+DOM::AbstractView Window::toAbstractView() const
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return DOM::AbstractView();
+ return part->document().defaultView();
+}
+
+void Window::scheduleClose()
+{
+ kdDebug(6070) << "Window::scheduleClose window.close() " << m_frame << endl;
+ Q_ASSERT(winq);
+ QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) );
+}
+
+void Window::closeNow()
+{
+ if (m_frame.isNull() || m_frame->m_part.isNull()) {
+ kdDebug(6070) << k_funcinfo << "part is deleted already" << endl;
+ } else {
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part) {
+ kdDebug(6070) << "closeNow on non KHTML part" << endl;
+ } else {
+ //kdDebug(6070) << k_funcinfo << " -> closing window" << endl;
+ // We want to make sure that window.open won't find this part by name.
+ part->setName( 0 );
+ part->deleteLater();
+ part = 0;
+ }
+ }
+}
+
+void Window::afterScriptExecution()
+{
+ DOM::DocumentImpl::updateDocumentsRendering();
+ QValueList<DelayedAction> delayedActions = m_delayed;
+ m_delayed.clear();
+ QValueList<DelayedAction>::Iterator it = delayedActions.begin();
+ for ( ; it != delayedActions.end() ; ++it )
+ {
+ switch ((*it).actionId) {
+ case DelayedClose:
+ scheduleClose();
+ return; // stop here, in case of multiple actions
+ case DelayedGoHistory:
+ goHistory( (*it).param.toInt() );
+ break;
+ case NullAction:
+ // FIXME: anything needs to be done here? This is warning anyways.
+ break;
+ };
+ }
+}
+
+bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const
+{
+ if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access
+ kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
+ return false;
+ }
+ if (!activePart) {
+ kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
+ return false;
+ }
+ if ( activePart == m_frame->m_part ) // Not calling from another frame, no problem.
+ return true;
+
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return true; // not a KHTMLPart
+
+ if ( part->document().isNull() )
+ return true; // allow to access a window that was just created (e.g. with window.open("about:blank"))
+
+ DOM::HTMLDocument thisDocument = part->htmlDocument();
+ if ( thisDocument.isNull() ) {
+ kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl;
+ return false;
+ }
+
+ KHTMLPart *activeKHTMLPart = ::qt_cast<KHTMLPart *>(activePart);
+ if (!activeKHTMLPart)
+ return true; // not a KHTMLPart
+
+ DOM::HTMLDocument actDocument = activeKHTMLPart->htmlDocument();
+ if ( actDocument.isNull() ) {
+ kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
+ return false;
+ }
+ DOM::DOMString actDomain = actDocument.domain();
+ DOM::DOMString thisDomain = thisDocument.domain();
+
+ if ( actDomain == thisDomain ) {
+#ifdef KJS_VERBOSE
+ //kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl;
+#endif
+ return true;
+ }
+
+ kdDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
+ // TODO after 3.1: throw security exception (exec->setException())
+ return false;
+}
+
+void Window::setListener(ExecState *exec, int eventId, Value func)
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part || !isSafeScript(exec))
+ return;
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
+ if (!doc)
+ return;
+
+ doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
+}
+
+Value Window::getListener(ExecState *exec, int eventId) const
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part || !isSafeScript(exec))
+ return Undefined();
+ DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(part->htmlDocument().handle());
+ if (!doc)
+ return Undefined();
+
+ DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId);
+ if (listener && static_cast<JSEventListener*>(listener)->listenerObjImp())
+ return static_cast<JSEventListener*>(listener)->listenerObj();
+ else
+ return Null();
+}
+
+
+JSEventListener *Window::getJSEventListener(const Value& val, bool html)
+{
+ // This function is so hot that it's worth coding it directly with imps.
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part || val.type() != ObjectType)
+ return 0;
+
+ // It's ObjectType, so it must be valid.
+ Object listenerObject = Object::dynamicCast(val);
+ ObjectImp *listenerObjectImp = listenerObject.imp();
+
+ // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!)
+ if (!listenerObject.implementsCall() && part && part->jScript() && part->jScript()->interpreter())
+ {
+ Interpreter *interpreter = part->jScript()->interpreter();
+
+ // 'listener' probably is an EventListener object containing a 'handleEvent' function.
+ Value handleEventValue = listenerObject.get(interpreter->globalExec(), Identifier("handleEvent"));
+ Object handleEventObject = Object::dynamicCast(handleEventValue);
+
+ if(handleEventObject.isValid() && handleEventObject.implementsCall())
+ {
+ listenerObject = handleEventObject;
+ listenerObjectImp = handleEventObject.imp();
+ }
+ }
+
+ JSEventListener *existingListener = jsEventListeners[listenerObjectImp];
+ if (existingListener) {
+ if ( existingListener->isHTMLEventListener() != html )
+ // The existingListener will have the wrong type, so onclick= will behave like addEventListener or vice versa.
+ kdWarning() << "getJSEventListener: event listener already found but with html=" << !html << " - please report this, we thought it would never happen" << endl;
+ return existingListener;
+ }
+
+ // Note that the JSEventListener constructor adds it to our jsEventListeners list
+ return new JSEventListener(listenerObject, listenerObjectImp, Object(this), html);
+}
+
+JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, const QString& name, DOM::NodeImpl *node)
+{
+ return new JSLazyEventListener(code, name, Object(this), node);
+}
+
+void Window::clear( ExecState *exec )
+{
+ delete winq;
+ winq = 0L;
+ // Get rid of everything, those user vars could hold references to DOM nodes
+ deleteAllProperties( exec );
+
+ // Break the dependency between the listeners and their object
+ QPtrDictIterator<JSEventListener> it(jsEventListeners);
+ for (; it.current(); ++it)
+ it.current()->clear();
+ // Forget about the listeners (the DOM::NodeImpls will delete them)
+ jsEventListeners.clear();
+
+ if (m_frame) {
+ KJSProxy* proxy = m_frame->m_jscript;
+ if (proxy) // i.e. JS not disabled
+ {
+ winq = new WindowQObject(this);
+ // Now recreate a working global object for the next URL that will use us
+ KJS::Interpreter *interpreter = proxy->interpreter();
+ interpreter->initGlobalObject();
+ }
+ }
+}
+
+void Window::setCurrentEvent( DOM::Event *evt )
+{
+ m_evt = evt;
+ //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
+}
+
+void Window::goURL(ExecState* exec, const QString& url, bool lockHistory)
+{
+ Window* active = Window::retrieveActive(exec);
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ KHTMLPart *active_part = ::qt_cast<KHTMLPart *>(active->part());
+ // Complete the URL using the "active part" (running interpreter)
+ if (active_part && part) {
+ if (url[0] == QChar('#')) {
+ part->gotoAnchor(url.mid(1));
+ } else {
+ QString dstUrl = active_part->htmlDocument().completeURL(url).string();
+ kdDebug(6070) << "Window::goURL dstUrl=" << dstUrl << endl;
+
+ // check if we're allowed to inject javascript
+ // SYNC check with khtml_part.cpp::slotRedirect!
+ if ( isSafeScript(exec) ||
+ dstUrl.find(QString::fromLatin1("javascript:"), 0, false) != 0 )
+ part->scheduleRedirection(-1,
+ dstUrl,
+ lockHistory);
+ }
+ } else if (!part && !m_frame->m_part.isNull()) {
+ KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part);
+ if (b)
+ b->emit openURLRequest(m_frame->m_frame->element()->getDocument()->completeURL(url));
+ kdDebug() << "goURL for ROPart" << endl;
+ }
+}
+
+KParts::ReadOnlyPart *Window::part() const {
+ return m_frame.isNull() ? 0L : static_cast<KParts::ReadOnlyPart *>(m_frame->m_part);
+}
+
+void Window::delayedGoHistory( int steps )
+{
+ m_delayed.append( DelayedAction( DelayedGoHistory, steps ) );
+}
+
+void Window::goHistory( int steps )
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if(!part)
+ // TODO history readonlypart
+ return;
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if(!ext)
+ return;
+ KParts::BrowserInterface *iface = ext->browserInterface();
+
+ if ( !iface )
+ return;
+
+ iface->callMethod( "goHistory(int)", steps );
+ //emit ext->goHistory(steps);
+}
+
+void KJS::Window::resizeTo(QWidget* tl, int width, int height)
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if(!part)
+ // TODO resizeTo readonlypart
+ return;
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (!ext) {
+ kdDebug(6070) << "Window::resizeTo found no browserExtension" << endl;
+ return;
+ }
+
+ // Security check: within desktop limits and bigger than 100x100 (per spec)
+ if ( width < 100 || height < 100 ) {
+ kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl;
+ return;
+ }
+
+ QRect sg = KGlobalSettings::desktopGeometry(tl);
+
+ if ( width > sg.width() || height > sg.height() ) {
+ kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl;
+ return;
+ }
+
+ kdDebug(6070) << "resizing to " << width << "x" << height << endl;
+
+ emit ext->resizeTopLevelWidget( width, height );
+
+ // If the window is out of the desktop, move it up/left
+ // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker)
+ int right = tl->x() + tl->frameGeometry().width();
+ int bottom = tl->y() + tl->frameGeometry().height();
+ int moveByX = 0;
+ int moveByY = 0;
+ if ( right > sg.right() )
+ moveByX = - right + sg.right(); // always <0
+ if ( bottom > sg.bottom() )
+ moveByY = - bottom + sg.bottom(); // always <0
+ if ( moveByX || moveByY )
+ emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY );
+}
+
+Value Window::openWindow(ExecState *exec, const List& args)
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ if (!part)
+ return Undefined();
+ KHTMLView *widget = part->view();
+ Value v = args[0];
+ QString str;
+ if (v.isValid() && !v.isA(UndefinedType))
+ str = v.toString(exec).qstring();
+
+ // prepare arguments
+ KURL url;
+ if (!str.isEmpty())
+ {
+ KHTMLPart* p = ::qt_cast<KHTMLPart *>(Window::retrieveActive(exec)->m_frame->m_part);
+ if ( p )
+ url = p->htmlDocument().completeURL(str).string();
+ if ( !p ||
+ !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) )
+ return Undefined();
+ }
+
+ KHTMLSettings::KJSWindowOpenPolicy policy =
+ part->settings()->windowOpenPolicy(part->url().host());
+ if ( policy == KHTMLSettings::KJSWindowOpenAsk ) {
+ emit part->browserExtension()->requestFocus(part);
+ QString caption;
+ if (!part->url().host().isEmpty())
+ caption = part->url().host() + " - ";
+ caption += i18n( "Confirmation: JavaScript Popup" );
+ if ( KMessageBox::questionYesNo(widget,
+ str.isEmpty() ?
+ i18n( "This site is requesting to open up a new browser "
+ "window via JavaScript.\n"
+ "Do you want to allow this?" ) :
+ i18n( "<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />"
+ "Do you want to allow this?</qt>").arg(KStringHandler::csqueeze(url.htmlURL(), 100)),
+ caption, i18n("Allow"), i18n("Do Not Allow") ) == KMessageBox::Yes )
+ policy = KHTMLSettings::KJSWindowOpenAllow;
+ } else if ( policy == KHTMLSettings::KJSWindowOpenSmart )
+ {
+ // window.open disabled unless from a key/mouse event
+ if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed())
+ policy = KHTMLSettings::KJSWindowOpenAllow;
+ }
+
+ QString frameName = args.size() > 1 ? args[1].toString(exec).qstring() : QString("_blank");
+
+ v = args[2];
+ QString features;
+ if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
+ features = v.toString(exec).qstring();
+ // Buggy scripts have ' at beginning and end, cut those
+ if (features.startsWith("\'") && features.endsWith("\'"))
+ features = features.mid(1, features.length()-2);
+ }
+
+ if ( policy != KHTMLSettings::KJSWindowOpenAllow ) {
+ if ( url.isEmpty() )
+ part->setSuppressedPopupIndicator(true, 0);
+ else {
+ part->setSuppressedPopupIndicator(true, part);
+ m_suppressedWindowInfo.append( SuppressedWindowInfo( url, frameName, features ) );
+ }
+ return Undefined();
+ } else {
+ return executeOpenWindow(exec, url, frameName, features);
+ }
+}
+
+Value Window::executeOpenWindow(ExecState *exec, const KURL& url, const QString& frameName, const QString& features)
+{
+ KHTMLPart *p = ::qt_cast<KHTMLPart *>(m_frame->m_part);
+ KHTMLView *widget = p->view();
+ KParts::WindowArgs winargs;
+
+ // scan feature argument
+ if (!features.isEmpty()) {
+ // specifying window params means false defaults
+ winargs.menuBarVisible = false;
+ winargs.toolBarsVisible = false;
+ winargs.statusBarVisible = false;
+ winargs.scrollBarsVisible = false;
+ QStringList flist = QStringList::split(',', features);
+ QStringList::ConstIterator it = flist.begin();
+ while (it != flist.end()) {
+ QString s = *it++;
+ QString key, val;
+ int pos = s.find('=');
+ if (pos >= 0) {
+ key = s.left(pos).stripWhiteSpace().lower();
+ val = s.mid(pos + 1).stripWhiteSpace().lower();
+ QRect screen = KGlobalSettings::desktopGeometry(widget->topLevelWidget());
+
+ if (key == "left" || key == "screenx") {
+ winargs.x = (int)val.toFloat() + screen.x();
+ if (winargs.x < screen.x() || winargs.x > screen.right())
+ winargs.x = screen.x(); // only safe choice until size is determined
+ } else if (key == "top" || key == "screeny") {
+ winargs.y = (int)val.toFloat() + screen.y();
+ if (winargs.y < screen.y() || winargs.y > screen.bottom())
+ winargs.y = screen.y(); // only safe choice until size is determined
+ } else if (key == "height") {
+ winargs.height = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
+ if (winargs.height > screen.height()) // should actually check workspace
+ winargs.height = screen.height();
+ if (winargs.height < 100)
+ winargs.height = 100;
+ } else if (key == "width") {
+ winargs.width = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
+ if (winargs.width > screen.width()) // should actually check workspace
+ winargs.width = screen.width();
+ if (winargs.width < 100)
+ winargs.width = 100;
+ } else {
+ goto boolargs;
+ }
+ continue;
+ } else {
+ // leaving away the value gives true
+ key = s.stripWhiteSpace().lower();
+ val = "1";
+ }
+ boolargs:
+ if (key == "menubar")
+ winargs.menuBarVisible = (val == "1" || val == "yes");
+ else if (key == "toolbar")
+ winargs.toolBarsVisible = (val == "1" || val == "yes");
+ else if (key == "location") // ### missing in WindowArgs
+ winargs.toolBarsVisible = (val == "1" || val == "yes");
+ else if (key == "status" || key == "statusbar")
+ winargs.statusBarVisible = (val == "1" || val == "yes");
+ else if (key == "scrollbars")
+ winargs.scrollBarsVisible = (val == "1" || val == "yes");
+ else if (key == "resizable")
+ winargs.resizable = (val == "1" || val == "yes");
+ else if (key == "fullscreen")
+ winargs.fullscreen = (val == "1" || val == "yes");
+ }
+ }
+
+ KParts::URLArgs uargs;
+ uargs.frameName = frameName;
+
+ if ( uargs.frameName.lower() == "_top" )
+ {
+ while ( p->parentPart() )
+ p = p->parentPart();
+ Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
+ return Window::retrieve(p);
+ }
+ if ( uargs.frameName.lower() == "_parent" )
+ {
+ if ( p->parentPart() )
+ p = p->parentPart();
+ Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
+ return Window::retrieve(p);
+ }
+ if ( uargs.frameName.lower() == "_self")
+ {
+ Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/);
+ return Window::retrieve(p);
+ }
+ if ( uargs.frameName.lower() == "replace" )
+ {
+ Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/);
+ return Window::retrieve(p);
+ }
+ uargs.serviceType = "text/html";
+
+ // request window (new or existing if framename is set)
+ KParts::ReadOnlyPart *newPart = 0L;
+ emit p->browserExtension()->createNewWindow(KURL(), uargs,winargs,newPart);
+ if (newPart && ::qt_cast<KHTMLPart*>(newPart)) {
+ KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
+ //qDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window);
+ khtmlpart->setOpener(p);
+ khtmlpart->setOpenedByJS(true);
+ if (khtmlpart->document().isNull()) {
+ khtmlpart->begin();
+ khtmlpart->write("<HTML><BODY>");
+ khtmlpart->end();
+ if ( p->docImpl() ) {
+ //kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
+ khtmlpart->docImpl()->setDomain( p->docImpl()->domain());
+ khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
+ }
+ }
+ uargs.serviceType = QString::null;
+ if (uargs.frameName.lower() == "_blank")
+ uargs.frameName = QString::null;
+ if (!url.isEmpty())
+ emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
+ return Window::retrieve(khtmlpart); // global object
+ } else
+ return Undefined();
+}
+
+void Window::forgetSuppressedWindows()
+{
+ m_suppressedWindowInfo.clear();
+}
+
+void Window::showSuppressedWindows()
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>( m_frame->m_part );
+ KJS::Interpreter *interpreter = part->jScript()->interpreter();
+ ExecState *exec = interpreter->globalExec();
+
+ QValueList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo;
+ m_suppressedWindowInfo.clear();
+ QValueList<SuppressedWindowInfo>::Iterator it = suppressedWindowInfo.begin();
+ for ( ; it != suppressedWindowInfo.end() ; ++it ) {
+ executeOpenWindow(exec, (*it).url, (*it).frameName, (*it).features);
+ }
+}
+
+Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( Window, thisObj );
+
+ // these should work no matter whether the window is already
+ // closed or not
+ if (id == Window::ValueOf || id == Window::ToString) {
+ return String("[object Window]");
+ }
+
+ Window *window = static_cast<Window *>(thisObj.imp());
+ QString str, str2;
+
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
+ if (!part)
+ return Undefined();
+
+ KHTMLView *widget = part->view();
+ Value v = args[0];
+ UString s;
+ if (v.isValid() && !v.isA(UndefinedType)) {
+ s = v.toString(exec);
+ str = s.qstring();
+ }
+
+ QString caption;
+ if (part && !part->url().host().isEmpty())
+ caption = part->url().host() + " - ";
+ caption += "JavaScript"; // TODO: i18n
+ // functions that work everywhere
+ switch(id) {
+ case Window::Alert:
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ if ( part && part->xmlDocImpl() )
+ part->xmlDocImpl()->updateRendering();
+ if ( part )
+ emit part->browserExtension()->requestFocus(part);
+ KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str, QStyleSheetItem::WhiteSpaceNormal), caption);
+ return Undefined();
+ case Window::Confirm:
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ if ( part && part->xmlDocImpl() )
+ part->xmlDocImpl()->updateRendering();
+ if ( part )
+ emit part->browserExtension()->requestFocus(part);
+ return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), caption,
+ KStdGuiItem::ok(), KStdGuiItem::cancel()) == KMessageBox::Yes));
+ case Window::Prompt:
+#ifndef KONQ_EMBEDDED
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ if ( part && part->xmlDocImpl() )
+ part->xmlDocImpl()->updateRendering();
+ if ( part )
+ emit part->browserExtension()->requestFocus(part);
+ bool ok;
+ if (args.size() >= 2)
+ str2 = KInputDialog::getText(caption,
+ QStyleSheet::convertFromPlainText(str),
+ args[1].toString(exec).qstring(), &ok, widget);
+ else
+ str2 = KInputDialog::getText(caption,
+ QStyleSheet::convertFromPlainText(str),
+ QString::null, &ok, widget);
+ if ( ok )
+ return String(str2);
+ else
+ return Null();
+#else
+ return Undefined();
+#endif
+ case Window::GetComputedStyle: {
+ if ( !part || !part->xmlDocImpl() )
+ return Undefined();
+ DOM::Node arg0 = toNode(args[0]);
+ if (arg0.nodeType() != DOM::Node::ELEMENT_NODE)
+ return Undefined(); // throw exception?
+ else
+ return getDOMCSSStyleDeclaration(exec, part->document().defaultView().getComputedStyle(static_cast<DOM::Element>(arg0),
+ args[1].toString(exec).string()));
+ }
+ case Window::Open:
+ return window->openWindow(exec, args);
+ case Window::Close: {
+ /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm :
+ The close method closes only windows opened by JavaScript using the open method.
+ If you attempt to close any other window, a confirm is generated, which
+ lets the user choose whether the window closes.
+ This is a security feature to prevent "mail bombs" containing self.close().
+ However, if the window has only one document (the current one) in its
+ session history, the close is allowed without any confirm. This is a
+ special case for one-off windows that need to open other windows and
+ then dispose of themselves.
+ */
+ bool doClose = false;
+ if (!part->openedByJS())
+ {
+ // To conform to the SPEC, we only ask if the window
+ // has more than one entry in the history (NS does that too).
+ History history(exec,part);
+
+ if ( history.get( exec, "length" ).toInt32(exec) <= 1 )
+ {
+ doClose = true;
+ }
+ else
+ {
+ // Can we get this dialog with tabs??? Does it close the window or the tab in that case?
+ emit part->browserExtension()->requestFocus(part);
+ if ( KMessageBox::questionYesNo( window->part()->widget(),
+ i18n("Close window?"), i18n("Confirmation Required"),
+ KStdGuiItem::close(), KStdGuiItem::cancel() )
+ == KMessageBox::Yes )
+ doClose = true;
+ }
+ }
+ else
+ doClose = true;
+
+ if (doClose)
+ {
+ // If this is the current window (the one the interpreter runs in),
+ // then schedule a delayed close (so that the script terminates first).
+ // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name");
+ if ( Window::retrieveActive(exec) == window ) {
+ if (widget) {
+ // quit all dialogs of this view
+ // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash
+ widget->closeChildDialogs();
+ }
+ //kdDebug() << "scheduling delayed close" << endl;
+ // We'll close the window at the end of the script execution
+ Window* w = const_cast<Window*>(window);
+ w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) );
+ } else {
+ //kdDebug() << "closing NOW" << endl;
+ (const_cast<Window*>(window))->closeNow();
+ }
+ }
+ return Undefined();
+ }
+ case Window::Navigate:
+ window->goURL(exec, args[0].toString(exec).qstring(), false /*don't lock history*/);
+ return Undefined();
+ case Window::Focus: {
+ KHTMLSettings::KJSWindowFocusPolicy policy =
+ part->settings()->windowFocusPolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) {
+ widget->topLevelWidget()->raise();
+ KWin::deIconifyWindow( widget->topLevelWidget()->winId() );
+ widget->setActiveWindow();
+ emit part->browserExtension()->requestFocus(part);
+ }
+ return Undefined();
+ }
+ case Window::Blur:
+ // TODO
+ return Undefined();
+ case Window::BToA:
+ case Window::AToB: {
+ if (!s.is8Bit())
+ return Undefined();
+ QByteArray in, out;
+ char *binData = s.ascii();
+ in.setRawData( binData, s.size() );
+ if (id == Window::AToB)
+ KCodecs::base64Decode( in, out );
+ else
+ KCodecs::base64Encode( in, out );
+ in.resetRawData( binData, s.size() );
+ UChar *d = new UChar[out.size()];
+ for (uint i = 0; i < out.size(); i++)
+ d[i].uc = (uchar) out[i];
+ UString ret(d, out.size(), false /*no copy*/);
+ return String(ret);
+ }
+
+ };
+
+
+ // now unsafe functions..
+ if (!window->isSafeScript(exec))
+ return Undefined();
+
+ switch (id) {
+ case Window::ScrollBy:
+ if(args.size() == 2 && widget)
+ widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec));
+ return Undefined();
+ case Window::Scroll:
+ case Window::ScrollTo:
+ if(args.size() == 2 && widget)
+ widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec));
+ return Undefined();
+ case Window::MoveBy: {
+ KHTMLSettings::KJSWindowMovePolicy policy =
+ part->settings()->windowMovePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
+ {
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (ext) {
+ QWidget * tl = widget->topLevelWidget();
+ QRect sg = KGlobalSettings::desktopGeometry(tl);
+
+ QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) );
+ // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
+ if ( dest.x() >= sg.x() && dest.y() >= sg.x() &&
+ dest.x()+tl->width() <= sg.width()+sg.x() &&
+ dest.y()+tl->height() <= sg.height()+sg.y() )
+ emit ext->moveTopLevelWidget( dest.x(), dest.y() );
+ }
+ }
+ return Undefined();
+ }
+ case Window::MoveTo: {
+ KHTMLSettings::KJSWindowMovePolicy policy =
+ part->settings()->windowMovePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget)
+ {
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if (ext) {
+ QWidget * tl = widget->topLevelWidget();
+ QRect sg = KGlobalSettings::desktopGeometry(tl);
+
+ QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() );
+ // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
+ if ( dest.x() >= sg.x() && dest.y() >= sg.y() &&
+ dest.x()+tl->width() <= sg.width()+sg.x() &&
+ dest.y()+tl->height() <= sg.height()+sg.y() )
+ emit ext->moveTopLevelWidget( dest.x(), dest.y() );
+ }
+ }
+ return Undefined();
+ }
+ case Window::ResizeBy: {
+ KHTMLSettings::KJSWindowResizePolicy policy =
+ part->settings()->windowResizePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowResizeAllow
+ && args.size() == 2 && widget)
+ {
+ QWidget * tl = widget->topLevelWidget();
+ QRect geom = tl->frameGeometry();
+ window->resizeTo( tl,
+ geom.width() + args[0].toInt32(exec),
+ geom.height() + args[1].toInt32(exec) );
+ }
+ return Undefined();
+ }
+ case Window::ResizeTo: {
+ KHTMLSettings::KJSWindowResizePolicy policy =
+ part->settings()->windowResizePolicy(part->url().host());
+ if(policy == KHTMLSettings::KJSWindowResizeAllow
+ && args.size() == 2 && widget)
+ {
+ QWidget * tl = widget->topLevelWidget();
+ window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) );
+ }
+ return Undefined();
+ }
+ case Window::SetTimeout:
+ case Window::SetInterval: {
+ bool singleShot;
+ int i; // timeout interval
+ if (args.size() == 0)
+ return Undefined();
+ if (args.size() > 1) {
+ singleShot = (id == Window::SetTimeout);
+ i = args[1].toInt32(exec);
+ } else {
+ // second parameter is missing. Emulate Mozilla behavior.
+ singleShot = true;
+ i = 4;
+ }
+ if (v.isA(StringType)) {
+ int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot );
+ return Number(r);
+ }
+ else if (v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) {
+ Object func = Object::dynamicCast(v);
+ List funcArgs;
+ ListIterator it = args.begin();
+ int argno = 0;
+ while (it != args.end()) {
+ Value arg = it++;
+ if (argno++ >= 2)
+ funcArgs.append(arg);
+ }
+ if (args.size() < 2)
+ funcArgs.append(Number(i));
+ int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot );
+ return Number(r);
+ }
+ else
+ return Undefined();
+ }
+ case Window::ClearTimeout:
+ case Window::ClearInterval:
+ (const_cast<Window*>(window))->winq->clearTimeout(v.toInt32(exec));
+ return Undefined();
+ case Window::Print:
+ if ( widget ) {
+ // ### TODO emit onbeforeprint event
+ widget->print();
+ // ### TODO emit onafterprint event
+ }
+ case Window::CaptureEvents:
+ case Window::ReleaseEvents:
+ // Do nothing for now. These are NS-specific legacy calls.
+ break;
+ case Window::AddEventListener: {
+ JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
+ if (listener) {
+ DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
+ docimpl->addWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
+ }
+ return Undefined();
+ }
+ case Window::RemoveEventListener: {
+ JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]);
+ if (listener) {
+ DOM::DocumentImpl* docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle());
+ docimpl->removeWindowEventListener(DOM::EventImpl::typeToId(args[0].toString(exec).string()),listener,args[2].toBoolean(exec));
+ }
+ return Undefined();
+ }
+
+ }
+ return Undefined();
+}
+
+////////////////////// ScheduledAction ////////////////////////
+
+// KDE 4: Make those parameters const ... &
+ScheduledAction::ScheduledAction(Object _func, List _args, DateTimeMS _nextTime, int _interval, bool _singleShot,
+ int _timerId)
+{
+ //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl;
+ func = static_cast<ObjectImp*>(_func.imp());
+ args = _args;
+ isFunction = true;
+ singleShot = _singleShot;
+ nextTime = _nextTime;
+ interval = _interval;
+ executing = false;
+ timerId = _timerId;
+}
+
+// KDE 4: Make it const QString &
+ScheduledAction::ScheduledAction(QString _code, DateTimeMS _nextTime, int _interval, bool _singleShot, int _timerId)
+{
+ //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl;
+ //func = 0;
+ //args = 0;
+ func = 0;
+ code = _code;
+ isFunction = false;
+ singleShot = _singleShot;
+ nextTime = _nextTime;
+ interval = _interval;
+ executing = false;
+ timerId = _timerId;
+}
+
+bool ScheduledAction::execute(Window *window)
+{
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(window->m_frame->m_part);
+ if (!part || !part->jScriptEnabled())
+ return false;
+ ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter());
+
+ interpreter->setProcessingTimerCallback(true);
+
+ //kdDebug(6070) << "ScheduledAction::execute " << this << endl;
+ if (isFunction) {
+ if (func->implementsCall()) {
+ // #### check this
+ Q_ASSERT( part );
+ if ( part )
+ {
+ KJS::Interpreter *interpreter = part->jScript()->interpreter();
+ ExecState *exec = interpreter->globalExec();
+ Q_ASSERT( window == interpreter->globalObject().imp() );
+ Object obj( window );
+ func->call(exec,obj,args); // note that call() creates its own execution state for the func call
+ if (exec->hadException())
+ exec->clearException();
+
+ // Update our document's rendering following the execution of the timeout callback.
+ part->document().updateRendering();
+ }
+ }
+ }
+ else {
+ part->executeScript(DOM::Node(), code);
+ }
+
+ interpreter->setProcessingTimerCallback(false);
+ return true;
+}
+
+void ScheduledAction::mark()
+{
+ if (func && !func->marked())
+ func->mark();
+ args.mark();
+}
+
+ScheduledAction::~ScheduledAction()
+{
+ //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl;
+}
+
+////////////////////// WindowQObject ////////////////////////
+
+WindowQObject::WindowQObject(Window *w)
+ : parent(w)
+{
+ //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl;
+ if ( !parent->m_frame )
+ kdDebug(6070) << "WARNING: null part in " << k_funcinfo << endl;
+ else
+ connect( parent->m_frame, SIGNAL( destroyed() ),
+ this, SLOT( parentDestroyed() ) );
+ pausedTime = 0;
+ lastTimerId = 0;
+ currentlyDispatching = false;
+}
+
+WindowQObject::~WindowQObject()
+{
+ //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
+ parentDestroyed(); // reuse same code
+}
+
+void WindowQObject::parentDestroyed()
+{
+ killTimers();
+
+ QPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it)
+ delete it.current();
+ scheduledActions.clear();
+}
+
+int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot)
+{
+ int id = ++lastTimerId;
+ if (t < 10) t = 10;
+ DateTimeMS nextTime = DateTimeMS::now().addMSecs(-pausedTime + t);
+
+ ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id);
+ scheduledActions.append(action);
+ setNextTimer();
+ return id;
+}
+
+int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot)
+{
+ Object objFunc = Object::dynamicCast( func );
+ if (!objFunc.isValid())
+ return 0;
+ int id = ++lastTimerId;
+ if (t < 10) t = 10;
+
+ DateTimeMS nextTime = DateTimeMS::now().addMSecs(-pausedTime + t);
+ ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id);
+ scheduledActions.append(action);
+ setNextTimer();
+ return id;
+}
+
+void WindowQObject::clearTimeout(int timerId)
+{
+ QPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it) {
+ ScheduledAction *action = it.current();
+ if (action->timerId == timerId) {
+ scheduledActions.removeRef(action);
+ if (!action->executing)
+ delete action;
+ return;
+ }
+ }
+}
+
+bool WindowQObject::hasTimers() const
+{
+ return scheduledActions.count();
+}
+
+void WindowQObject::mark()
+{
+ QPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it)
+ it.current()->mark();
+}
+
+void WindowQObject::timerEvent(QTimerEvent *)
+{
+ killTimers();
+
+ if (scheduledActions.isEmpty())
+ return;
+
+ currentlyDispatching = true;
+
+
+ DateTimeMS currentActual = DateTimeMS::now();
+ DateTimeMS currentAdjusted = currentActual.addMSecs(-pausedTime);
+
+ // Work out which actions are to be executed. We take a separate copy of
+ // this list since the main one may be modified during action execution
+ QPtrList<ScheduledAction> toExecute;
+ QPtrListIterator<ScheduledAction> it(scheduledActions);
+ for (; it.current(); ++it)
+ if (currentAdjusted >= it.current()->nextTime)
+ toExecute.append(it.current());
+
+ // ### verify that the window can't be closed (and action deleted) during execution
+ it = QPtrListIterator<ScheduledAction>(toExecute);
+ for (; it.current(); ++it) {
+ ScheduledAction *action = it.current();
+ if (!scheduledActions.containsRef(action)) // removed by clearTimeout()
+ continue;
+
+ action->executing = true; // prevent deletion in clearTimeout()
+
+ if (parent->part()) {
+ bool ok = action->execute(parent);
+ if ( !ok ) // e.g. JS disabled
+ scheduledActions.removeRef( action );
+ }
+
+ if (action->singleShot) {
+ scheduledActions.removeRef(action);
+ }
+
+ action->executing = false;
+
+ if (!scheduledActions.containsRef(action))
+ delete action;
+ else
+ action->nextTime = action->nextTime.addMSecs(action->interval);
+ }
+
+ pausedTime += currentActual.msecsTo(DateTimeMS::now());
+
+ currentlyDispatching = false;
+
+ // Work out when next event is to occur
+ setNextTimer();
+}
+
+DateTimeMS DateTimeMS::addMSecs(int s) const
+{
+ DateTimeMS c = *this;
+ c.mTime = mTime.addMSecs(s);
+ if (s > 0)
+ {
+ if (c.mTime < mTime)
+ c.mDate = mDate.addDays(1);
+ }
+ else
+ {
+ if (c.mTime > mTime)
+ c.mDate = mDate.addDays(-1);
+ }
+ return c;
+}
+
+bool DateTimeMS::operator >(const DateTimeMS &other) const
+{
+ if (mDate > other.mDate)
+ return true;
+
+ if (mDate < other.mDate)
+ return false;
+
+ return mTime > other.mTime;
+}
+
+bool DateTimeMS::operator >=(const DateTimeMS &other) const
+{
+ if (mDate > other.mDate)
+ return true;
+
+ if (mDate < other.mDate)
+ return false;
+
+ return mTime >= other.mTime;
+}
+
+int DateTimeMS::msecsTo(const DateTimeMS &other) const
+{
+ int d = mDate.daysTo(other.mDate);
+ int ms = mTime.msecsTo(other.mTime);
+ return d*24*60*60*1000 + ms;
+}
+
+
+DateTimeMS DateTimeMS::now()
+{
+ DateTimeMS t;
+ QTime before = QTime::currentTime();
+ t.mDate = QDate::currentDate();
+ t.mTime = QTime::currentTime();
+ if (t.mTime < before)
+ t.mDate = QDate::currentDate(); // prevent race condition in hacky way :)
+ return t;
+}
+
+void WindowQObject::setNextTimer()
+{
+ if (currentlyDispatching)
+ return; // Will schedule at the end
+
+ if (scheduledActions.isEmpty())
+ return;
+
+ QPtrListIterator<ScheduledAction> it(scheduledActions);
+ DateTimeMS nextTime = it.current()->nextTime;
+ for (++it; it.current(); ++it)
+ if (nextTime > it.current()->nextTime)
+ nextTime = it.current()->nextTime;
+
+ DateTimeMS nextTimeActual = nextTime.addMSecs(pausedTime);
+ int nextInterval = DateTimeMS::now().msecsTo(nextTimeActual);
+ if (nextInterval < 0)
+ nextInterval = 0;
+ startTimer(nextInterval);
+}
+
+void WindowQObject::timeoutClose()
+{
+ parent->closeNow();
+}
+
+Value FrameArray::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl;
+#endif
+ if (part.isNull())
+ return Undefined();
+
+ QPtrList<KParts::ReadOnlyPart> frames = part->frames();
+ unsigned int len = frames.count();
+ if (p == lengthPropertyName)
+ return Number(len);
+ else if (p== "location") // non-standard property, but works in NS and IE
+ {
+ Object obj = Object::dynamicCast( Window::retrieve( part ) );
+ if ( obj.isValid() )
+ return obj.get( exec, "location" );
+ return Undefined();
+ }
+
+ // check for the name or number
+ KParts::ReadOnlyPart *frame = part->findFramePart(p.qstring());
+ if (!frame) {
+ bool ok;
+ unsigned int i = p.toArrayIndex(&ok);
+ if (ok && i < len)
+ frame = frames.at(i);
+ }
+
+ // we are potentially fetching a reference to a another Window object here.
+ // i.e. we may be accessing objects from another interpreter instance.
+ // Therefore we have to be a bit careful with memory management.
+ if (frame) {
+ return Window::retrieve(frame);
+ }
+
+ // Fun IE quirk: name lookup in there is actually done by document.all
+ // hence, it can find non-frame things (and even let them hide frame ones!)
+ // We don't quite do that, but do this as a fallback.
+ DOM::DocumentImpl* doc = static_cast<DOM::DocumentImpl*>(part->document().handle());
+ if (doc) {
+ DOM::HTMLCollectionImpl docuAll(doc, DOM::HTMLCollectionImpl::DOC_ALL);
+ DOM::NodeImpl* node = docuAll.namedItem(p.string());
+ if (node) {
+ if (node->id() == ID_FRAME || node->id() == ID_IFRAME) {
+ //Return the Window object.
+ KHTMLPart* part = static_cast<DOM::HTMLFrameElementImpl*>(node)->contentPart();
+ if (part)
+ return Value(Window::retrieveWindow(part));
+ else
+ return Undefined();
+ } else {
+ //Just a regular node..
+ return getDOMNode(exec, node);
+ }
+ }
+ } else {
+ kdWarning(6070) << "Missing own document in FrameArray::get()" << endl;
+ }
+
+ return ObjectImp::get(exec, p);
+}
+
+Value FrameArray::call(ExecState *exec, Object &/*thisObj*/, const List &args)
+{
+ //IE supports a subset of the get functionality as call...
+ //... basically, when the return is a window, it supports that, otherwise it
+ //errors out. We do a cheap-and-easy emulation of that, and just do the same
+ //thing as get does.
+ if (args.size() == 1)
+ return get(exec, Identifier(args[0].toString(exec)));
+
+ return Undefined();
+}
+
+
+////////////////////// Location Object ////////////////////////
+
+const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 };
+/*
+@begin LocationTable 11
+ hash Location::Hash DontDelete
+ host Location::Host DontDelete
+ hostname Location::Hostname DontDelete
+ href Location::Href DontDelete
+ pathname Location::Pathname DontDelete
+ port Location::Port DontDelete
+ protocol Location::Protocol DontDelete
+ search Location::Search DontDelete
+ [[==]] Location::EqualEqual DontDelete|ReadOnly
+ assign Location::Assign DontDelete|Function 1
+ toString Location::ToString DontDelete|Function 0
+ replace Location::Replace DontDelete|Function 1
+ reload Location::Reload DontDelete|Function 0
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(LocationFunc)
+Location::Location(khtml::ChildFrame *f) : m_frame(f)
+{
+ //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl;
+}
+
+Location::~Location()
+{
+ //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl;
+}
+
+KParts::ReadOnlyPart *Location::part() const {
+ return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : 0L;
+}
+
+Value Location::get(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
+#endif
+
+ if (m_frame.isNull() || m_frame->m_part.isNull())
+ return Undefined();
+
+ const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
+
+ // properties that work on all Location objects
+ if ( entry && entry->value == Replace )
+ return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+
+ // XSS check
+ const Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( !window || !window->isSafeScript(exec) )
+ return Undefined();
+
+ KURL url = m_frame->m_part->url();
+ if (entry)
+ switch (entry->value) {
+ case Hash:
+ return String( url.ref().isNull() ? QString("") : "#" + url.ref() );
+ case Host: {
+ UString str = url.host();
+ if (url.port())
+ str += ":" + QString::number((int)url.port());
+ return String(str);
+ // Note: this is the IE spec. The NS spec swaps the two, it says
+ // "The hostname property is the concatenation of the host and port properties, separated by a colon."
+ // Bleh.
+ }
+ case Hostname:
+ return String( url.host() );
+ case Href:
+ if (url.isEmpty())
+ return String("about:blank");
+ else if (!url.hasPath())
+ return String( url.prettyURL()+"/" );
+ else
+ return String( url.prettyURL() );
+ case Pathname:
+ if (url.isEmpty())
+ return String("");
+ return String( url.path().isEmpty() ? QString("/") : url.path() );
+ case Port:
+ return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") );
+ case Protocol:
+ return String( url.protocol()+":" );
+ case Search:
+ return String( url.query() );
+ case EqualEqual: // [[==]]
+ return String(toString(exec));
+ case ToString:
+ return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+ }
+ // Look for overrides
+ ValueImp * val = ObjectImp::getDirect(p);
+ if (val)
+ return Value(val);
+ if (entry && (entry->attr & Function))
+ return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr);
+
+ return Undefined();
+}
+
+void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr)
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_frame->m_part << endl;
+#endif
+ if (m_frame.isNull() || m_frame->m_part.isNull())
+ return;
+
+ const Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( !window )
+ return;
+
+ KURL url = m_frame->m_part->url();
+
+ const HashEntry *entry = Lookup::findEntry(&LocationTable, p);
+
+ if (entry) {
+
+ // XSS check. Only new hrefs can be set from other sites
+ if (entry->value != Href && !window->isSafeScript(exec))
+ return;
+
+ QString str = v.toString(exec).qstring();
+ switch (entry->value) {
+ case Href: {
+ KHTMLPart* p =::qt_cast<KHTMLPart*>(Window::retrieveActive(exec)->part());
+ if ( p )
+ url = p->htmlDocument().completeURL( str ).string();
+ else
+ url = str;
+ break;
+ }
+ case Hash:
+ // when the hash is already the same ignore it
+ if (str == url.ref()) return;
+ url.setRef(str);
+ break;
+ case Host: {
+ QString host = str.left(str.find(":"));
+ QString port = str.mid(str.find(":")+1);
+ url.setHost(host);
+ url.setPort(port.toUInt());
+ break;
+ }
+ case Hostname:
+ url.setHost(str);
+ break;
+ case Pathname:
+ url.setPath(str);
+ break;
+ case Port:
+ url.setPort(str.toUInt());
+ break;
+ case Protocol:
+ url.setProtocol(str);
+ break;
+ case Search:
+ url.setQuery(str);
+ break;
+ }
+ } else {
+ ObjectImp::put(exec, p, v, attr);
+ return;
+ }
+
+ Window::retrieveWindow(m_frame->m_part)->goURL(exec, url.url(), false /* don't lock history*/ );
+}
+
+Value Location::toPrimitive(ExecState *exec, Type) const
+{
+ if (m_frame) {
+ Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( window && window->isSafeScript(exec) )
+ return String(toString(exec));
+ }
+ return Undefined();
+}
+
+UString Location::toString(ExecState *exec) const
+{
+ if (m_frame) {
+ Window* window = Window::retrieveWindow( m_frame->m_part );
+ if ( window && window->isSafeScript(exec) )
+ {
+ KURL url = m_frame->m_part->url();
+ if (url.isEmpty())
+ return "about:blank";
+ else if (!url.hasPath())
+ return url.prettyURL()+"/";
+ else
+ return url.prettyURL();
+ }
+ }
+ return "";
+}
+
+Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( Location, thisObj );
+ Location *location = static_cast<Location *>(thisObj.imp());
+ KParts::ReadOnlyPart *part = location->part();
+
+ if (!part) return Undefined();
+
+ Window* window = Window::retrieveWindow(part);
+
+ if ( !window->isSafeScript(exec) && id != Location::Replace)
+ return Undefined();
+
+ switch (id) {
+ case Location::Assign:
+ case Location::Replace:
+ Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(),
+ id == Location::Replace);
+ break;
+ case Location::Reload: {
+ KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart *>(part);
+ if (khtmlpart)
+ khtmlpart->scheduleRedirection(-1, part->url().url(), true/*lock history*/);
+ else
+ part->openURL(part->url());
+ break;
+ }
+ case Location::ToString:
+ return String(location->toString(exec));
+ }
+ return Undefined();
+}
+
+////////////////////// External Object ////////////////////////
+
+const ClassInfo External::info = { "External", 0, 0, 0 };
+/*
+@begin ExternalTable 4
+ addFavorite External::AddFavorite DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(ExternalFunc)
+
+Value External::get(ExecState *exec, const Identifier &p) const
+{
+ return lookupGetFunction<ExternalFunc,ObjectImp>(exec,p,&ExternalTable,this);
+}
+
+Value ExternalFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( External, thisObj );
+ External *external = static_cast<External *>(thisObj.imp());
+
+ KHTMLPart *part = external->part;
+ if (!part)
+ return Undefined();
+
+ KHTMLView *widget = part->view();
+
+ switch (id) {
+ case External::AddFavorite:
+ {
+#ifndef KONQ_EMBEDDED
+ if (!widget->dialogsAllowed())
+ return Undefined();
+ part->xmlDocImpl()->updateRendering();
+ if (args.size() != 1 && args.size() != 2)
+ return Undefined();
+
+ QString url = args[0].toString(exec).qstring();
+ QString title;
+ if (args.size() == 2)
+ title = args[1].toString(exec).qstring();
+
+ // AK - don't do anything yet, for the moment i
+ // just wanted the base js handling code in cvs
+ return Undefined();
+
+ QString question;
+ if ( title.isEmpty() )
+ question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?")
+ .arg(url);
+ else
+ question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?")
+ .arg(url).arg(title);
+
+ emit part->browserExtension()->requestFocus(part);
+
+ QString caption;
+ if (!part->url().host().isEmpty())
+ caption = part->url().host() + " - ";
+ caption += i18n("JavaScript Attempted Bookmark Insert");
+
+ if (KMessageBox::warningYesNo(
+ widget, question, caption,
+ i18n("Insert"), i18n("Disallow")) == KMessageBox::Yes)
+ {
+ KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager();
+ mgr->addBookmarkDialog(url,title);
+ }
+#else
+ return Undefined();
+#endif
+ break;
+ }
+ default:
+ return Undefined();
+ }
+
+ return Undefined();
+}
+
+////////////////////// History Object ////////////////////////
+
+const ClassInfo History::info = { "History", 0, 0, 0 };
+/*
+@begin HistoryTable 4
+ length History::Length DontDelete|ReadOnly
+ back History::Back DontDelete|Function 0
+ forward History::Forward DontDelete|Function 0
+ go History::Go DontDelete|Function 1
+@end
+*/
+IMPLEMENT_PROTOFUNC_DOM(HistoryFunc)
+
+Value History::get(ExecState *exec, const Identifier &p) const
+{
+ return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this);
+}
+
+Value History::getValueProperty(ExecState *, int token) const
+{
+ // if previous or next is implemented, make sure its not a major
+ // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/)
+ switch (token) {
+ case Length:
+ {
+ if ( !part )
+ return Number( 0 );
+
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if ( !ext )
+ return Number( 0 );
+
+ KParts::BrowserInterface *iface = ext->browserInterface();
+ if ( !iface )
+ return Number( 0 );
+
+ QVariant length = iface->property( "historyLength" );
+
+ if ( length.type() != QVariant::UInt )
+ return Number( 0 );
+
+ return Number( length.toUInt() );
+ }
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token << endl;
+ return Undefined();
+ }
+}
+
+Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( History, thisObj );
+ History *history = static_cast<History *>(thisObj.imp());
+
+ Value v = args[0];
+ Number n;
+ if(v.isValid())
+ n = v.toInteger(exec);
+
+ int steps;
+ switch (id) {
+ case History::Back:
+ steps = -1;
+ break;
+ case History::Forward:
+ steps = 1;
+ break;
+ case History::Go:
+ steps = n.intValue();
+ break;
+ default:
+ return Undefined();
+ }
+
+ // Special case for go(0) from a frame -> reload only the frame
+ // go(i!=0) from a frame navigates into the history of the frame only,
+ // in both IE and NS (but not in Mozilla).... we can't easily do that
+ // in Konqueror...
+ if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter
+ {
+ history->part->openURL( history->part->url() ); /// ## need args.reload=true?
+ } else
+ {
+ // Delay it.
+ // Testcase: history.back(); alert("hello");
+ Window* window = Window::retrieveWindow( history->part );
+ window->delayedGoHistory( steps );
+ }
+ return Undefined();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef Q_WS_QWS
+
+const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 };
+
+bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const
+{
+ if ( p.qstring().startsWith( "goHistory" ) ) return false;
+
+ return true;
+}
+
+Value Konqueror::get(ExecState *exec, const Identifier &p) const
+{
+ if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" )
+ return Undefined();
+
+ KParts::BrowserExtension *ext = part->browserExtension();
+ if ( ext ) {
+ KParts::BrowserInterface *iface = ext->browserInterface();
+ if ( iface ) {
+ QVariant prop = iface->property( p.qstring().latin1() );
+
+ if ( prop.isValid() ) {
+ switch( prop.type() ) {
+ case QVariant::Int:
+ return Number( prop.toInt() );
+ case QVariant::String:
+ return String( prop.toString() );
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return Value( new KonquerorFunc(exec, this, p.qstring().latin1() ) );
+}
+
+Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args)
+{
+ KParts::BrowserExtension *ext = konqueror->part->browserExtension();
+
+ if (!ext)
+ return Undefined();
+
+ KParts::BrowserInterface *iface = ext->browserInterface();
+
+ if ( !iface )
+ return Undefined();
+
+ QCString n = m_name.data();
+ n += "()";
+ iface->callMethod( n.data(), QVariant() );
+
+ return Undefined();
+}
+
+UString Konqueror::toString(ExecState *) const
+{
+ return UString("[object Konqueror]");
+}
+
+#endif
+/////////////////////////////////////////////////////////////////////////////
+} //namespace KJS
+
+#include "kjs_window.moc"