You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2936 lines
97 KiB
2936 lines
97 KiB
// -*- c-basic-offset: 2 -*-
|
|
/*
|
|
* This file is part of the KDE libraries
|
|
* Copyright (C) 2000-2003 Harri Porten (porten@kde.org)
|
|
* Copyright (C) 2001-2003 David Faure (faure@kde.org)
|
|
* 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 "tdehtmlview.h"
|
|
#include "tdehtml_part.h"
|
|
#include "tdehtmlpart_p.h"
|
|
#include "tdehtml_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 <tqstylesheet.h>
|
|
#include <tqtimer.h>
|
|
#include <tqpaintdevicemetrics.h>
|
|
#include <tqapplication.h>
|
|
#include <kdebug.h>
|
|
#include <kmessagebox.h>
|
|
#include <kinputdialog.h>
|
|
#include <klocale.h>
|
|
#include <kmdcodec.h>
|
|
#include <tdeparts/browserinterface.h>
|
|
#include <twin.h>
|
|
|
|
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
|
|
#include <twinmodule.h> // schroder
|
|
#endif
|
|
|
|
#ifndef KONQ_EMBEDDED
|
|
#include <kbookmarkmanager.h>
|
|
#endif
|
|
#include <kglobalsettings.h>
|
|
#include <assert.h>
|
|
#include <tqstyle.h>
|
|
#include <tqobjectlist.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:
|
|
TQGuardedPtr<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:
|
|
TQGuardedPtr<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:
|
|
TQGuardedPtr<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;
|
|
TQCString 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
|
|
TQWidget *thisWidget = Window::retrieveActive(exec)->part()->widget();
|
|
TQRect sg = TDEGlobalSettings::desktopGeometry(thisWidget);
|
|
|
|
switch( token ) {
|
|
case Height:
|
|
return Number(sg.height());
|
|
case Width:
|
|
return Number(sg.width());
|
|
case ColorDepth:
|
|
case PixelDepth: {
|
|
TQPaintDeviceMetrics m(TQApplication::desktop());
|
|
return Number(m.depth());
|
|
}
|
|
case AvailLeft: {
|
|
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
|
|
TQRect 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
|
|
TQRect 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
|
|
TQRect 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
|
|
TQRect 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(tdehtml::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 = ::tqqt_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 = ::tqqt_cast<KHTMLPart *>(p);
|
|
KJSProxy *proxy = 0L;
|
|
if (!part) {
|
|
part = ::tqqt_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 = ::tqqt_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 = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
|
|
if (!part)
|
|
return false;
|
|
|
|
TQString 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) {
|
|
TQPtrList<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 = ::tqqt_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
|
|
TQString 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();
|
|
tdehtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size
|
|
return Number(part->view()->visibleHeight());
|
|
case InnerWidth:
|
|
if (!part->view())
|
|
return Undefined();
|
|
tdehtml::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();
|
|
TQRect sg = TDEGlobalSettings::desktopGeometry(part->view());
|
|
return Number(part->view()->mapToGlobal(TQPoint(0,0)).x() + sg.x());
|
|
}
|
|
case ScreenTop:
|
|
case ScreenY: {
|
|
if (!part->view())
|
|
return Undefined();
|
|
TQRect sg = TDEGlobalSettings::desktopGeometry(part->view());
|
|
return Number(part->view()->mapToGlobal(TQPoint(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) {
|
|
TQPtrList<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 = ::tqqt_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 = ::tqqt_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);
|
|
TQTimer::singleShot( 0, winq, TQT_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 = ::tqqt_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();
|
|
TQValueList<DelayedAction> delayedActions = m_delayed;
|
|
m_delayed.clear();
|
|
TQValueList<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 = ::tqqt_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 = ::tqqt_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 = ::tqqt_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 = ::tqqt_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 = ::tqqt_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 TQString& code, const TQString& 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
|
|
TQPtrDictIterator<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 TQString& url, bool lockHistory)
|
|
{
|
|
Window* active = Window::retrieveActive(exec);
|
|
KHTMLPart *part = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
|
|
KHTMLPart *active_part = ::tqqt_cast<KHTMLPart *>(active->part());
|
|
// Complete the URL using the "active part" (running interpreter)
|
|
if (active_part && part) {
|
|
if (url[0] == TQChar('#')) {
|
|
part->gotoAnchor(url.mid(1));
|
|
} else {
|
|
TQString 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 tdehtml_part.cpp::slotRedirect!
|
|
if ( isSafeScript(exec) ||
|
|
dstUrl.find(TQString::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 = ::tqqt_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(TQWidget* tl, int width, int height)
|
|
{
|
|
KHTMLPart *part = ::tqqt_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;
|
|
}
|
|
|
|
TQRect sg = TDEGlobalSettings::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 = ::tqqt_cast<KHTMLPart *>(m_frame->m_part);
|
|
if (!part)
|
|
return Undefined();
|
|
KHTMLView *widget = part->view();
|
|
Value v = args[0];
|
|
TQString str;
|
|
if (v.isValid() && !v.isA(UndefinedType))
|
|
str = v.toString(exec).qstring();
|
|
|
|
// prepare arguments
|
|
KURL url;
|
|
if (!str.isEmpty())
|
|
{
|
|
KHTMLPart* p = ::tqqt_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);
|
|
TQString 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;
|
|
}
|
|
|
|
TQString frameName = args.size() > 1 ? args[1].toString(exec).qstring() : TQString("_blank");
|
|
|
|
v = args[2];
|
|
TQString 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 TQString& frameName, const TQString& features)
|
|
{
|
|
KHTMLPart *p = ::tqqt_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;
|
|
TQStringList flist = TQStringList::split(',', features);
|
|
TQStringList::ConstIterator it = flist.begin();
|
|
while (it != flist.end()) {
|
|
TQString s = *it++;
|
|
TQString key, val;
|
|
int pos = s.find('=');
|
|
if (pos >= 0) {
|
|
key = s.left(pos).stripWhiteSpace().lower();
|
|
val = s.mid(pos + 1).stripWhiteSpace().lower();
|
|
TQRect screen = TDEGlobalSettings::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*tqApp->style().pixelMetric( TQStyle::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*tqApp->style().pixelMetric( TQStyle::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 && ::tqqt_cast<KHTMLPart*>(newPart)) {
|
|
KHTMLPart *tdehtmlpart = static_cast<KHTMLPart*>(newPart);
|
|
//tqDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window);
|
|
tdehtmlpart->setOpener(p);
|
|
tdehtmlpart->setOpenedByJS(true);
|
|
if (tdehtmlpart->document().isNull()) {
|
|
tdehtmlpart->begin();
|
|
tdehtmlpart->write("<HTML><BODY>");
|
|
tdehtmlpart->end();
|
|
if ( p->docImpl() ) {
|
|
//kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl;
|
|
tdehtmlpart->docImpl()->setDomain( p->docImpl()->domain());
|
|
tdehtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() );
|
|
}
|
|
}
|
|
uargs.serviceType = TQString::null;
|
|
if (uargs.frameName.lower() == "_blank")
|
|
uargs.frameName = TQString::null;
|
|
if (!url.isEmpty())
|
|
emit tdehtmlpart->browserExtension()->openURLRequest(url,uargs);
|
|
return Window::retrieve(tdehtmlpart); // global object
|
|
} else
|
|
return Undefined();
|
|
}
|
|
|
|
void Window::forgetSuppressedWindows()
|
|
{
|
|
m_suppressedWindowInfo.clear();
|
|
}
|
|
|
|
void Window::showSuppressedWindows()
|
|
{
|
|
KHTMLPart *part = ::tqqt_cast<KHTMLPart *>( m_frame->m_part );
|
|
KJS::Interpreter *interpreter = part->jScript()->interpreter();
|
|
ExecState *exec = interpreter->globalExec();
|
|
|
|
TQValueList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo;
|
|
m_suppressedWindowInfo.clear();
|
|
TQValueList<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());
|
|
TQString str, str2;
|
|
|
|
KHTMLPart *part = ::tqqt_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();
|
|
}
|
|
|
|
TQString 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, TQStyleSheet::convertFromPlainText(str, TQStyleSheetItem::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, TQStyleSheet::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,
|
|
TQStyleSheet::convertFromPlainText(str),
|
|
args[1].toString(exec).qstring(), &ok, widget);
|
|
else
|
|
str2 = KInputDialog::getText(caption,
|
|
TQStyleSheet::convertFromPlainText(str),
|
|
TQString::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();
|
|
TQByteArray 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) {
|
|
TQWidget * tl = widget->topLevelWidget();
|
|
TQRect sg = TDEGlobalSettings::desktopGeometry(tl);
|
|
|
|
TQPoint dest = tl->pos() + TQPoint( 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) {
|
|
TQWidget * tl = widget->topLevelWidget();
|
|
TQRect sg = TDEGlobalSettings::desktopGeometry(tl);
|
|
|
|
TQPoint 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)
|
|
{
|
|
TQWidget * tl = widget->topLevelWidget();
|
|
TQRect 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)
|
|
{
|
|
TQWidget * 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 TQString &
|
|
ScheduledAction::ScheduledAction(TQString _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 = ::tqqt_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, TQT_SIGNAL( destroyed() ),
|
|
this, TQT_SLOT( parentDestroyed() ) );
|
|
pausedTime = 0;
|
|
lastTimerId = 0;
|
|
currentlyDispatching = false;
|
|
}
|
|
|
|
WindowQObject::~WindowQObject()
|
|
{
|
|
//kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl;
|
|
parentDestroyed(); // reuse same code
|
|
}
|
|
|
|
void WindowQObject::parentDestroyed()
|
|
{
|
|
killTimers();
|
|
|
|
TQPtrListIterator<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)
|
|
{
|
|
TQPtrListIterator<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()
|
|
{
|
|
TQPtrListIterator<ScheduledAction> it(scheduledActions);
|
|
for (; it.current(); ++it)
|
|
it.current()->mark();
|
|
}
|
|
|
|
void WindowQObject::timerEvent(TQTimerEvent *)
|
|
{
|
|
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
|
|
TQPtrList<ScheduledAction> toExecute;
|
|
TQPtrListIterator<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 = TQPtrListIterator<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 = TQT_TQTIME_OBJECT(mTime.addMSecs(s));
|
|
if (s > 0)
|
|
{
|
|
if (c.mTime < mTime)
|
|
c.mDate = TQT_TQDATE_OBJECT(mDate.addDays(1));
|
|
}
|
|
else
|
|
{
|
|
if (c.mTime > mTime)
|
|
c.mDate = TQT_TQDATE_OBJECT(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;
|
|
TQTime before = TQTime::currentTime();
|
|
t.mDate = TQDate::currentDate();
|
|
t.mTime = TQTime::currentTime();
|
|
if (t.mTime < before)
|
|
t.mDate = TQDate::currentDate(); // prevent race condition in hacky way :)
|
|
return t;
|
|
}
|
|
|
|
void WindowQObject::setNextTimer()
|
|
{
|
|
if (currentlyDispatching)
|
|
return; // Will schedule at the end
|
|
|
|
if (scheduledActions.isEmpty())
|
|
return;
|
|
|
|
TQPtrListIterator<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();
|
|
|
|
TQPtrList<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(tdehtml::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() ? TQString("") : "#" + url.ref() );
|
|
case Host: {
|
|
UString str = url.host();
|
|
if (url.port())
|
|
str += ":" + TQString::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() ? TQString("/") : url.path() );
|
|
case Port:
|
|
return String( url.port() ? TQString::number((int)url.port()) : TQString::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;
|
|
|
|
TQString str = v.toString(exec).qstring();
|
|
switch (entry->value) {
|
|
case Href: {
|
|
KHTMLPart* p =::tqqt_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: {
|
|
TQString host = str.left(str.find(":"));
|
|
TQString 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 *tdehtmlpart = ::tqqt_cast<KHTMLPart *>(part);
|
|
if (tdehtmlpart)
|
|
tdehtmlpart->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();
|
|
|
|
TQString url = args[0].toString(exec).qstring();
|
|
TQString 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();
|
|
|
|
TQString 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);
|
|
|
|
TQString 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 );
|
|
|
|
TQVariant length = iface->property( "historyLength" );
|
|
|
|
if ( length.type() != TQVariant::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 ) {
|
|
TQVariant prop = iface->property( p.qstring().latin1() );
|
|
|
|
if ( prop.isValid() ) {
|
|
switch( prop.type() ) {
|
|
case TQVariant::Int:
|
|
return Number( prop.toInt() );
|
|
case TQVariant::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();
|
|
|
|
TQCString n = m_name.data();
|
|
n += "()";
|
|
iface->callMethod( n.data(), TQVariant() );
|
|
|
|
return Undefined();
|
|
}
|
|
|
|
UString Konqueror::toString(ExecState *) const
|
|
{
|
|
return UString("[object Konqueror]");
|
|
}
|
|
|
|
#endif
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
} //namespace KJS
|
|
|
|
#include "kjs_window.moc"
|