📄 kjs_window.cpp
字号:
DOM::DOMString targetDomain = targetDocument->domain();
// Always allow local pages to execute any JS.
if (targetDomain.isNull())
return true;
DOM::DOMString originDomain = originDocument->domain();
// if this document is being initially loaded as empty by its parent
// or opener, allow access from any document in the same domain as
// the parent or opener.
if (shouldLoadAsEmptyDocument(targetPart->url())) {
KHTMLPart *ancestorPart = targetPart->opener() ? targetPart->opener() : targetPart->parentPart();
while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
ancestorPart = ancestorPart->parentPart();
}
if (ancestorPart)
originDomain = ancestorPart->xmlDocImpl()->domain();
}
if ( targetDomain == originDomain )
return true;
if (Interpreter::shouldPrintExceptions()) {
printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n",
targetDocument->URL().latin1(), originDocument->URL().latin1());
}
#ifndef NOKIA_CHANGES
QString message;
message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n",
targetDocument->URL().latin1(), originDocument->URL().latin1());
KWQ(targetPart)->addMessageToConsole(message, 1, QString()); //fixme: provide a real line number and sourceurl
#endif
return false;
}
bool Window::isSafeScript(ExecState *exec) const
{
if (m_part.isNull()) { // part deleted ? can't grant access
kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl;
return false;
}
KHTMLPart *activePart = static_cast<KJS::ScriptInterpreter *>( exec->dynamicInterpreter() )->part();
if (!activePart) {
kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl;
return false;
}
if ( activePart == m_part ) // Not calling from another frame, no problem.
return true;
// JS may be attempting to access the "window" object, which should be valid,
// even if the document hasn't been constructed yet. If the document doesn't
// exist yet allow JS to access the window object.
if (!m_part->xmlDocImpl())
return true;
DOM::DocumentImpl* thisDocument = m_part->xmlDocImpl();
DOM::DocumentImpl* actDocument = activePart->xmlDocImpl();
if (!actDocument) {
kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl;
return false;
}
DOM::DOMString actDomain = actDocument->domain();
// Always allow local pages to execute any JS.
if (actDomain.isNull())
return true;
DOM::DOMString thisDomain = thisDocument->domain();
// if this document is being initially loaded as empty by its parent
// or opener, allow access from any document in the same domain as
// the parent or opener.
if (shouldLoadAsEmptyDocument(m_part->url())) {
KHTMLPart *ancestorPart = m_part->opener() ? m_part->opener() : m_part->parentPart();
while (ancestorPart && shouldLoadAsEmptyDocument(ancestorPart->url())) {
ancestorPart = ancestorPart->parentPart();
}
if (ancestorPart)
thisDomain = ancestorPart->xmlDocImpl()->domain();
}
//kdDebug(6070) << "current domain:" << actDomain.string() << ", frame domain:" << thisDomain.string() << endl;
if ( actDomain == thisDomain )
return true;
#if APPLE_CHANGES
if (Interpreter::shouldPrintExceptions()) {
printf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n",
thisDocument->URL().latin1(), actDocument->URL().latin1());
}
#ifndef NOKIA_CHANGES
QString message;
message.sprintf("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains must match.\n",
thisDocument->URL().latin1(), actDocument->URL().latin1());
KWQ(m_part)->addMessageToConsole(message, 1, QString());
#endif
#endif
kdWarning(6070) << "Javascript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl;
return false;
}
void Window::setListener(ExecState *exec, int eventId, Value func)
{
if (!isSafeScript(exec))
return;
DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle());
if (!doc)
return;
doc->setHTMLWindowEventListener(eventId,getJSEventListener(func,true));
}
Value Window::getListener(ExecState *exec, int eventId) const
{
if (!isSafeScript(exec))
return Undefined();
DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_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.
if (val.type() != ObjectType)
return 0;
ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
JSEventListener *existingListener = jsEventListeners[listenerObject];
if (existingListener)
return existingListener;
// Note that the JSEventListener constructor adds it to our jsEventListeners list
return new JSEventListener(Object(listenerObject), Object(this), html);
}
JSUnprotectedEventListener *Window::getJSUnprotectedEventListener(const Value& val, bool html)
{
// This function is so hot that it's worth coding it directly with imps.
if (val.type() != ObjectType)
return 0;
ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp());
JSUnprotectedEventListener *existingListener = jsUnprotectedEventListeners[listenerObject];
if (existingListener)
return existingListener;
// Note that the JSUnprotectedEventListener constructor adds it to
// our jsUnprotectedEventListeners list
return new JSUnprotectedEventListener(Object(listenerObject), Object(this), html);
}
JSLazyEventListener *Window::getJSLazyEventListener(const QString& code, DOM::NodeImpl *node, int lineNumber)
{
return new JSLazyEventListener(code, Object(this), node, lineNumber);
}
void Window::clear( ExecState *exec )
{
KJS::Interpreter::lock();
kdDebug(6070) << "Window::clear " << this << endl;
delete winq;
winq = new WindowQObject(this);;
// Get rid of everything, those user vars could hold references to DOM nodes
deleteAllProperties( exec );
// Really delete those properties, so that the DOM nodes get deref'ed
KJS::Collector::collect();
// Now recreate a working global object for the next URL that will use us
KJS::Interpreter *interpreter = KJSProxy::proxy( m_part )->interpreter();
interpreter->initGlobalObject();
KJS::Interpreter::unlock();
}
void Window::setCurrentEvent( DOM::Event *evt )
{
m_evt = evt;
//kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl;
}
Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
{
if (!thisObj.inherits(&Window::info)) {
Object err = Error::create(exec,TypeError);
exec->setException(err);
return err;
}
Window *window = static_cast<Window *>(thisObj.imp());
QString str, str2;
KHTMLPart *part = window->m_part;
if (!part)
return Undefined();
KHTMLView *widget = part->view();
Value v = args[0];
UString s = v.toString(exec);
str = s.qstring();
switch (id) {
case Window::Alert:
if (part && part->xmlDocImpl())
part->xmlDocImpl()->updateRendering();
#if APPLE_CHANGES
KWQ(part)->runJavaScriptAlert(str);
#else
KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript");
#endif
return Undefined();
case Window::Confirm:
if (part && part->xmlDocImpl())
part->xmlDocImpl()->updateRendering();
#if NOKIA_CHANGES
{
QString str1 = args.size() >= 2 ? args[1].toString(exec).qstring() : QString::null;
QString str2 = args.size() >= 3 ? args[1].toString(exec).qstring() : QString::null;
return Boolean(KWQ(part)->runJavaScriptConfirm(str, str1, str2));
}
#elif APPLE_CHANGES
return Boolean(KWQ(part)->runJavaScriptConfirm(str));
#else
return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript",
i18n("OK"), i18n("Cancel")) == KMessageBox::Yes));
#endif
case Window::Prompt:
if (part && part->xmlDocImpl())
part->xmlDocImpl()->updateRendering();
bool ok;
#if APPLE_CHANGES
ok = KWQ(part)->runJavaScriptPrompt(str, args.size() >= 2 ? args[1].toString(exec).qstring() : QString::null, str2);
#else
if (args.size() >= 2)
str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
QStyleSheet::convertFromPlainText(str),
QLineEdit::Normal,
args[1].toString(exec).qstring(), &ok);
else
str2 = QInputDialog::getText(i18n("Konqueror: Prompt"),
QStyleSheet::convertFromPlainText(str),
QLineEdit::Normal,
QString::null, &ok);
#endif
if ( ok )
return String(str2);
else
return Null();
case Window::Open:
{
#ifndef NOKIA_CHANGES
KConfig *config = new KConfig("konquerorrc");
config->setGroup("Java/JavaScript Settings");
#if !APPLE_CHANGES
int policy = config->readUnsignedNumEntry( "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
#else
int policy = config->readUnsignedNumEntry( part->settings(), "WindowOpenPolicy", 0 ); // 0=allow, 1=ask, 2=deny, 3=smart
#endif
delete config;
if ( policy == 1 ) {
#if !APPLE_CHANGES
if ( KMessageBox::questionYesNo(widget,
i18n( "This site is trying to open up a new browser "
"window using Javascript.\n"
"Do you want to allow this?" ),
i18n( "Confirmation: Javascript Popup" ) ) == KMessageBox::Yes )
#endif
policy = 0;
} else if ( policy == 3 ) // smart
{
// window.open disabled unless from a key/mouse event
if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture())
#if !APPLE_CHANGES
policy = 0;
#else
{
policy = 0;
LOG(PopupBlocking, "Allowed JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
} else {
LOG(PopupBlocking, "Blocked JavaScript window open of %s", args[0].toString(exec).qstring().ascii());
}
#endif
}
#else
int policy = 0;
#endif
QString frameName = !args[1].isNull() && args[1].type() != UndefinedType ?
args[1].toString(exec).qstring()
: QString("_blank");
if ( policy != 0 && !(part->findFrame(frameName) || frameName == "_top" || frameName == "_parent" || frameName == "_self")) {
return Undefined();
} else {
if (v.type() == UndefinedType)
str = QString();
KParts::WindowArgs winargs;
// scan feature argument
v = args[2];
QString features;
if (!v.isNull() && v.type() != UndefinedType && v.toString(exec).size() > 0) {
features = v.toString(exec).qstring();
// specifying window params means false defaults
winargs.menuBarVisible = false;
winargs.toolBarsVisible = false;
winargs.statusBarVisible = false;
#if APPLE_CHANGES
winargs.scrollbarsVisible = true;
#endif
QStringList flist = QStringList::split(',', features);
QStringList::ConstIterator it = flist.begin();
while (it != flist.end()) {
QString s = *it++;
QString key, val;
int pos = s.find('=');
if (pos >= 0) {
key = s.left(pos).stripWhiteSpace().lower();
val = s.mid(pos + 1).stripWhiteSpace().lower();
int spacePos = val.find(' ');
if (spacePos != -1) {
val = val.left(spacePos);
}
int scnum = QApplication::desktop()->screenNumber(widget->topLevelWidget());
QRect screen = QApplication::desktop()->screenGeometry(scnum);
if (key == "left" || key == "screenx") {
bool ok;
double d = val.toDouble(&ok);
if (d != 0 || ok) {
d += screen.x();
if (d < screen.x() || d > screen.right())
d = screen.x(); // only safe choice until size is determined
winargs.x = (int)d;
#if APPLE_CHANGES
winargs.xSet = true;
#endif
}
} else if (key == "top" || key == "screeny") {
bool ok;
double d = val.toDouble(&ok);
if (d != 0 || ok) {
d += screen.y();
if (d < screen.y() || d > screen.bottom())
d = screen.y(); // only safe choice until size is determined
winargs.y = (int)d;
#if APPLE_CHANGES
winargs.ySet = true;
#endif
}
} else if (key == "height") {
bool ok;
double d = val.toDouble(&ok);
if (d != 0 || ok) {
#if !APPLE_CHANGES
d += 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2;
#endif
if (d > screen.height()) // should actually check workspace
d = screen.height();
if (d < 100)
d = 100;
winargs.height = (int)d;
#if APPLE_CHANGES
winargs.heightSet = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -