Warning, file /frameworks/khtml/src/ecma/kjs_window.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 2000-2003 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2001-2003 David Faure (faure@kde.org) 0005 * Copyright (C) 2003 Apple Computer, Inc. 0006 * Copyright (C) 2006, 2008-2010 Maksim Orlovich (maksim@kde.org) 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Library General Public 0010 * License as published by the Free Software Foundation; either 0011 * version 2 of the License, or (at your option) any later version. 0012 * 0013 * This library is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * Library General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU Library General Public 0019 * License along with this library; if not, write to the Free Software 0020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0021 */ 0022 0023 #include "kjs_window.h" 0024 #include "kjs_data.h" 0025 0026 #include <khtmlview.h> 0027 #include <khtml_part.h> 0028 #include <khtmlpart_p.h> 0029 #include <khtml_settings.h> 0030 #include <xml/dom2_eventsimpl.h> 0031 #include <xml/dom_docimpl.h> 0032 #include <dom/html_document.h> 0033 #include <html/html_documentimpl.h> 0034 #include <rendering/render_frames.h> 0035 0036 #include <config-khtml.h> 0037 0038 #include <QTimer> 0039 #include <QApplication> 0040 #include <QDesktopWidget> 0041 #include <qinputdialog.h> 0042 #include "khtml_debug.h" 0043 #include <kmessagebox.h> 0044 #include <klocalizedstring.h> 0045 #include <kparts/browserinterface.h> 0046 #include <kwindowsystem.h> 0047 0048 #ifndef KONQ_EMBEDDED 0049 #include <kbookmarkmanager.h> 0050 #include <kbookmarkdialog.h> 0051 #endif 0052 #include <assert.h> 0053 #include <QStyle> 0054 #include <QTextDocument> 0055 #include <kstringhandler.h> 0056 0057 #include "kjs_proxy.h" 0058 #include "kjs_navigator.h" 0059 #include "kjs_mozilla.h" 0060 #include "kjs_html.h" 0061 #include "kjs_range.h" 0062 #include "kjs_traversal.h" 0063 #include "kjs_css.h" 0064 #include "kjs_events.h" 0065 #include "kjs_audio.h" 0066 #include "kjs_context2d.h" 0067 #include "kjs_xpath.h" 0068 #include "kjs_scriptable.h" 0069 #include "xmlhttprequest.h" 0070 #include "xmlserializer.h" 0071 #include "domparser.h" 0072 #include "kjs_arraybuffer.h" 0073 #include "kjs_arraytyped.h" 0074 0075 #include <rendering/render_replaced.h> 0076 0077 using namespace KJS; 0078 using namespace DOM; 0079 0080 namespace KJS 0081 { 0082 0083 class History : public JSObject 0084 { 0085 friend class HistoryFunc; 0086 public: 0087 History(ExecState *exec, KHTMLPart *p) 0088 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { } 0089 using KJS::JSObject::getOwnPropertySlot; 0090 bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override; 0091 JSValue *getValueProperty(ExecState *exec, int token) const; 0092 const ClassInfo *classInfo() const override 0093 { 0094 return &info; 0095 } 0096 static const ClassInfo info; 0097 enum { Back, Forward, Go, Length }; 0098 private: 0099 QPointer<KHTMLPart> part; 0100 }; 0101 0102 class External : public JSObject 0103 { 0104 friend class ExternalFunc; 0105 public: 0106 External(ExecState *exec, KHTMLPart *p) 0107 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()), part(p) { } 0108 using KJS::JSObject::getOwnPropertySlot; 0109 bool getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) override; 0110 const ClassInfo *classInfo() const override 0111 { 0112 return &info; 0113 } 0114 static const ClassInfo info; 0115 enum { AddFavorite }; 0116 private: 0117 QPointer<KHTMLPart> part; 0118 }; 0119 } //namespace KJS 0120 0121 #include "kjs_window.lut.h" 0122 0123 namespace KJS 0124 { 0125 0126 ////////////////////// Screen Object //////////////////////// 0127 0128 // table for screen object 0129 /* 0130 @begin ScreenTable 7 0131 height Screen::Height DontEnum|ReadOnly 0132 width Screen::Width DontEnum|ReadOnly 0133 colorDepth Screen::ColorDepth DontEnum|ReadOnly 0134 pixelDepth Screen::PixelDepth DontEnum|ReadOnly 0135 availLeft Screen::AvailLeft DontEnum|ReadOnly 0136 availTop Screen::AvailTop DontEnum|ReadOnly 0137 availHeight Screen::AvailHeight DontEnum|ReadOnly 0138 availWidth Screen::AvailWidth DontEnum|ReadOnly 0139 @end 0140 */ 0141 0142 const ClassInfo Screen::info = { "Screen", nullptr, &ScreenTable, nullptr }; 0143 0144 // We set the object prototype so that toString is implemented 0145 Screen::Screen(ExecState *exec) 0146 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) {} 0147 0148 bool Screen::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0149 { 0150 #ifdef KJS_VERBOSE 0151 qCDebug(KHTML_LOG) << "Screen::getPropertyName " << propertyName.qstring(); 0152 #endif 0153 return getStaticValueSlot<Screen, JSObject>(exec, &ScreenTable, this, propertyName, slot); 0154 } 0155 0156 JSValue *Screen::getValueProperty(ExecState *exec, int token) const 0157 { 0158 QWidget *thisWidget = Window::retrieveActive(exec)->part()->widget(); 0159 QRect sg = QApplication::desktop()->screenGeometry(thisWidget); 0160 0161 switch (token) { 0162 case Height: 0163 return jsNumber(sg.height()); 0164 case Width: 0165 return jsNumber(sg.width()); 0166 case ColorDepth: 0167 case PixelDepth: 0168 return jsNumber(thisWidget->depth()); 0169 case AvailLeft: { 0170 #if HAVE_X11 && ! defined K_WS_QTONLY 0171 QRect clipped = KWindowSystem::workArea().intersected(sg); 0172 return jsNumber(clipped.x() - sg.x()); 0173 #else 0174 return jsNumber(10); 0175 #endif 0176 } 0177 case AvailTop: { 0178 #if HAVE_X11 && ! defined K_WS_QTONLY 0179 QRect clipped = KWindowSystem::workArea().intersected(sg); 0180 return jsNumber(clipped.y() - sg.y()); 0181 #else 0182 return jsNumber(10); 0183 #endif 0184 } 0185 case AvailHeight: { 0186 #if HAVE_X11 && ! defined K_WS_QTONLY 0187 QRect clipped = KWindowSystem::workArea().intersected(sg); 0188 return jsNumber(clipped.height()); 0189 #else 0190 return jsNumber(100); 0191 #endif 0192 } 0193 case AvailWidth: { 0194 #if HAVE_X11 && ! defined K_WS_QTONLY 0195 QRect clipped = KWindowSystem::workArea().intersected(sg); 0196 return jsNumber(clipped.width()); 0197 #else 0198 return jsNumber(100); 0199 #endif 0200 } 0201 default: 0202 // qCDebug(KHTML_LOG) << "WARNING: Screen::getValueProperty unhandled token " << token; 0203 return jsUndefined(); 0204 } 0205 } 0206 0207 ////////////////////// Console Object //////////////////////// 0208 0209 // table for console object 0210 /* 0211 @begin ConsoleTable 7 0212 assert Console::Assert DontEnum|Function 1 0213 log Console::Log DontEnum|Function 1 0214 debug Console::Debug DontEnum|Function 1 0215 warn Console::Warn DontEnum|Function 1 0216 error Console::Error DontEnum|Function 1 0217 info Console::Info DontEnum|Function 1 0218 clear Console::Clear DontEnum|Function 0 0219 @end 0220 */ 0221 0222 KJS_IMPLEMENT_PROTOFUNC(ConsoleFunc) 0223 0224 const ClassInfo Console::info = { "Console", nullptr, &ConsoleTable, nullptr }; 0225 0226 // We set the object prototype so that toString is implemented 0227 Console::Console(ExecState *exec) 0228 : JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()) {} 0229 0230 bool Console::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0231 { 0232 #ifdef KJS_VERBOSE 0233 qCDebug(KHTML_LOG) << "Console::getPropertyName " << propertyName.qstring(); 0234 #endif 0235 return getStaticFunctionSlot<ConsoleFunc, JSObject>(exec, &ConsoleTable, this, propertyName, slot); 0236 } 0237 0238 void printMessage(Console::MessageType msgType, const UString &message) 0239 { 0240 const char *type; 0241 switch (msgType) { 0242 case Console::DebugType: 0243 type = "DEBUG"; 0244 break; 0245 case Console::ErrorType: 0246 type = "ERROR"; 0247 break; 0248 case Console::InfoType: 0249 type = "INFO"; 0250 break; 0251 case Console::LogType: 0252 type = "LOG"; 0253 break; 0254 case Console::WarnType: 0255 type = "WARN"; 0256 break; 0257 0258 default: 0259 type = "UNKNOWN"; 0260 ASSERT_NOT_REACHED(); 0261 } 0262 // qCDebug(KHTML_LOG) << "[" << type << "]\t" << message.ascii(); 0263 } 0264 0265 JSValue *consolePrintf(ExecState *exec, Console::MessageType msgType, const List &args) 0266 { 0267 if (!args[0]->isString()) { 0268 return jsUndefined(); 0269 } 0270 UString output = args[0]->toString(exec); 0271 if (exec->hadException()) { 0272 return jsUndefined(); 0273 } 0274 int size = output.size(); 0275 int arg = 1; 0276 int last = 0; 0277 UString composedOutput; 0278 for (int i = 0; i < size; ++i) { 0279 if (!(output[i] == '%')) { 0280 continue; 0281 } 0282 if (i + 1 >= size) { 0283 break; 0284 } 0285 0286 UString replace; 0287 switch (output[i + 1].uc) { 0288 case 's': { 0289 if (args[arg]->isString()) { 0290 replace = args[arg]->toString(exec); 0291 ++arg; 0292 } 0293 break; 0294 } 0295 case 'f': 0296 case 'i': 0297 case 'd': { 0298 if (args[arg]->isNumber()) { 0299 double val = args[arg]->toNumber(exec); 0300 replace = UString::from(val); 0301 ++arg; 0302 } 0303 break; 0304 } 0305 case 'o': 0306 case 'c': 0307 //not yet implemented skip me 0308 i += 1; 0309 ++arg; 0310 0311 default: 0312 continue; 0313 } 0314 if (exec->hadException()) { 0315 return jsUndefined(); 0316 } 0317 composedOutput += output.substr(last, i - last); 0318 composedOutput += replace; 0319 i += 1; 0320 last = i + 1; 0321 } 0322 0323 if (last == 0) { // no % magic used, just copy the original 0324 composedOutput = output; 0325 } else { 0326 composedOutput += output.substr(last); 0327 } 0328 0329 printMessage(msgType, composedOutput); 0330 return jsUndefined(); 0331 } 0332 0333 JSValue *ConsoleFunc::callAsFunction(ExecState *exec, JSObject * /*thisObj*/, const List &args) 0334 { 0335 switch (id) { 0336 case Console::Assert: { 0337 JSType type = args[0]->type(); 0338 bool assertFailed = false; 0339 switch (type) { 0340 case UnspecifiedType: 0341 case NullType: 0342 case UndefinedType: 0343 assertFailed = true; 0344 break; 0345 case BooleanType: 0346 assertFailed = !args[0]->getBoolean(); 0347 break; 0348 case NumberType: 0349 case StringType: 0350 case ObjectType: 0351 case GetterSetterType: 0352 assertFailed = false; 0353 break; 0354 default: 0355 assertFailed = true; 0356 ASSERT_NOT_REACHED(); 0357 break; 0358 } 0359 0360 if (assertFailed) { 0361 // ignore further parameter for now.. 0362 if (args.size() > 1 && args[1]->isString()) { 0363 printMessage(Console::ErrorType, args[1]->getString()); 0364 } else { 0365 printMessage(Console::ErrorType, "Assert failed!"); 0366 } 0367 } 0368 return jsUndefined(); 0369 } 0370 case Console::Log: 0371 return consolePrintf(exec, Console::LogType, args); 0372 case Console::Debug: 0373 return consolePrintf(exec, Console::DebugType, args); 0374 case Console::Warn: 0375 return consolePrintf(exec, Console::WarnType, args); 0376 case Console::Error: 0377 return consolePrintf(exec, Console::ErrorType, args); 0378 case Console::Info: 0379 return consolePrintf(exec, Console::InfoType, args); 0380 case Console::Clear: 0381 // TODO: clear the console 0382 return jsUndefined(); 0383 } 0384 return jsUndefined(); 0385 } 0386 0387 ////////////////////// Window Object //////////////////////// 0388 0389 const ClassInfo Window::info = { "Window", &DOMAbstractView::info, &WindowTable, nullptr }; 0390 0391 /* 0392 @begin WindowTable 233 0393 atob Window::AToB DontDelete|Function 1 0394 btoa Window::BToA DontDelete|Function 1 0395 closed Window::Closed DontDelete|ReadOnly 0396 crypto Window::Crypto DontDelete|ReadOnly 0397 defaultStatus Window::DefaultStatus DontDelete 0398 defaultstatus Window::DefaultStatus DontDelete 0399 status Window::Status DontDelete 0400 document Window::Document DontDelete|ReadOnly 0401 frameElement Window::FrameElement DontDelete|ReadOnly 0402 frames Window::Frames DontDelete 0403 history Window::_History DontDelete|ReadOnly 0404 external Window::_External DontDelete|ReadOnly 0405 event Window::Event DontDelete|ReadOnly 0406 innerHeight Window::InnerHeight DontDelete|ReadOnly 0407 innerWidth Window::InnerWidth DontDelete|ReadOnly 0408 length Window::Length DontDelete 0409 location Window::_Location DontDelete 0410 name Window::Name DontDelete 0411 navigator Window::_Navigator DontDelete|ReadOnly 0412 clientInformation Window::ClientInformation DontDelete|ReadOnly 0413 konqueror Window::_Konqueror DontDelete 0414 offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly 0415 opener Window::Opener DontDelete|ReadOnly 0416 outerHeight Window::OuterHeight DontDelete|ReadOnly 0417 outerWidth Window::OuterWidth DontDelete|ReadOnly 0418 pageXOffset Window::PageXOffset DontDelete|ReadOnly 0419 pageYOffset Window::PageYOffset DontDelete|ReadOnly 0420 parent Window::Parent DontDelete 0421 personalbar Window::Personalbar DontDelete 0422 screenX Window::ScreenX DontDelete|ReadOnly 0423 screenY Window::ScreenY DontDelete|ReadOnly 0424 scrollbars Window::Scrollbars DontDelete|ReadOnly 0425 scroll Window::Scroll DontDelete|Function 2 0426 scrollBy Window::ScrollBy DontDelete|Function 2 0427 scrollTo Window::ScrollTo DontDelete|Function 2 0428 scrollX Window::ScrollX DontDelete|ReadOnly 0429 scrollY Window::ScrollY DontDelete|ReadOnly 0430 moveBy Window::MoveBy DontDelete|Function 2 0431 moveTo Window::MoveTo DontDelete|Function 2 0432 postMessage Window::PostMessage DontDelete|Function 2 0433 resizeBy Window::ResizeBy DontDelete|Function 2 0434 resizeTo Window::ResizeTo DontDelete|Function 2 0435 self Window::Self DontDelete|ReadOnly 0436 window Window::_Window DontDelete|ReadOnly 0437 top Window::Top DontDelete 0438 screen Window::_Screen DontDelete|ReadOnly 0439 console Window::_Console DontDelete|ReadOnly 0440 alert Window::Alert DontDelete|Function 1 0441 confirm Window::Confirm DontDelete|Function 1 0442 prompt Window::Prompt DontDelete|Function 2 0443 open Window::Open DontDelete|Function 3 0444 setTimeout Window::SetTimeout DontDelete|Function 2 0445 clearTimeout Window::ClearTimeout DontDelete|Function 1 0446 focus Window::Focus DontDelete|Function 0 0447 blur Window::Blur DontDelete|Function 0 0448 close Window::Close DontDelete|Function 0 0449 setInterval Window::SetInterval DontDelete|Function 2 0450 clearInterval Window::ClearInterval DontDelete|Function 1 0451 captureEvents Window::CaptureEvents DontDelete|Function 0 0452 releaseEvents Window::ReleaseEvents DontDelete|Function 0 0453 print Window::Print DontDelete|Function 0 0454 addEventListener Window::AddEventListener DontDelete|Function 3 0455 removeEventListener Window::RemoveEventListener DontDelete|Function 3 0456 getSelection Window::GetSelection DontDelete|Function 0 0457 # Normally found in prototype. Add to window object itself to make them 0458 # accessible in closed and cross-site windows 0459 valueOf Window::ValueOf DontEnum|DontDelete|Function 0 0460 toString Window::ToString DontEnum|DontDelete|Function 0 0461 # IE extension 0462 navigate Window::Navigate DontDelete|Function 1 0463 # Mozilla extension 0464 sidebar Window::SideBar DontDelete|DontEnum 0465 getComputedStyle Window::GetComputedStyle DontDelete|Function 2 0466 0467 # Warning, when adding a function to this object you need to add a case in Window::get 0468 0469 # Event handlers 0470 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect, 0471 # ondeactivate, onhelp, onmovestart/end, onresizestart/end. 0472 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one). 0473 onabort Window::Onabort DontDelete 0474 onblur Window::Onblur DontDelete 0475 onchange Window::Onchange DontDelete 0476 onclick Window::Onclick DontDelete 0477 ondblclick Window::Ondblclick DontDelete 0478 ondragdrop Window::Ondragdrop DontDelete 0479 onerror Window::Onerror DontDelete 0480 onfocus Window::Onfocus DontDelete 0481 onkeydown Window::Onkeydown DontDelete 0482 onkeypress Window::Onkeypress DontDelete 0483 onkeyup Window::Onkeyup DontDelete 0484 onload Window::Onload DontDelete 0485 onmessage Window::Onmessage DontDelete 0486 onmousedown Window::Onmousedown DontDelete 0487 onmousemove Window::Onmousemove DontDelete 0488 onmouseout Window::Onmouseout DontDelete 0489 onmouseover Window::Onmouseover DontDelete 0490 onmouseup Window::Onmouseup DontDelete 0491 onmove Window::Onmove DontDelete 0492 onreset Window::Onreset DontDelete 0493 onresize Window::Onresize DontDelete 0494 onscroll Window::Onscroll DontDelete 0495 onselect Window::Onselect DontDelete 0496 onsubmit Window::Onsubmit DontDelete 0497 onunload Window::Onunload DontDelete 0498 onhashchange Window::Onhashchange DontDelete 0499 0500 # Constructors/constant tables 0501 Node Window::Node DontEnum|DontDelete 0502 Event Window::EventCtor DontEnum|DontDelete 0503 Range Window::Range DontEnum|DontDelete 0504 NodeFilter Window::NodeFilter DontEnum|DontDelete 0505 NodeList Window::NodeList DontEnum|DontDelete 0506 DOMException Window::DOMException DontEnum|DontDelete 0507 RangeException Window::RangeException DontEnum|DontDelete 0508 CSSRule Window::CSSRule DontEnum|DontDelete 0509 MutationEvent Window::MutationEventCtor DontEnum|DontDelete 0510 MessageEvent Window::MessageEventCtor DontEnum|DontDelete 0511 KeyboardEvent Window::KeyboardEventCtor DontEnum|DontDelete 0512 EventException Window::EventExceptionCtor DontEnum|DontDelete 0513 HashChangeEvent Window::HashChangeEventCtor DontEnum|DontDelete 0514 Audio Window::Audio DontEnum|DontDelete 0515 Image Window::Image DontEnum|DontDelete 0516 Option Window::Option DontEnum|DontDelete 0517 XMLHttpRequest Window::XMLHttpRequest DontEnum|DontDelete 0518 XMLSerializer Window::XMLSerializer DontEnum|DontDelete 0519 DOMParser Window::DOMParser DontEnum|DontDelete 0520 ArrayBuffer Window::ArrayBuffer DontEnum|DontDelete 0521 Int8Array Window::Int8Array DontEnum|DontDelete 0522 Uint8Array Window::Uint8Array DontEnum|DontDelete 0523 Int16Array Window::Int16Array DontEnum|DontDelete 0524 Uint16Array Window::Uint16Array DontEnum|DontDelete 0525 Int32Array Window::Int32Array DontEnum|DontDelete 0526 Uint32Array Window::Uint32Array DontEnum|DontDelete 0527 Float32Array Window::Float32Array DontEnum|DontDelete 0528 Float64Array Window::Float64Array DontEnum|DontDelete 0529 0530 # Mozilla dom emulation ones. 0531 Element Window::ElementCtor DontEnum|DontDelete 0532 Document Window::DocumentCtor DontEnum|DontDelete 0533 DocumentFragment Window::DocumentFragmentCtor DontEnum|DontDelete 0534 #this one is an alias since we don't have a separate XMLDocument 0535 XMLDocument Window::DocumentCtor DontEnum|DontDelete 0536 HTMLElement Window::HTMLElementCtor DontEnum|DontDelete 0537 HTMLDocument Window::HTMLDocumentCtor DontEnum|DontDelete 0538 HTMLHtmlElement Window::HTMLHtmlElementCtor DontEnum|DontDelete 0539 HTMLHeadElement Window::HTMLHeadElementCtor DontEnum|DontDelete 0540 HTMLLinkElement Window::HTMLLinkElementCtor DontEnum|DontDelete 0541 HTMLTitleElement Window::HTMLTitleElementCtor DontEnum|DontDelete 0542 HTMLMetaElement Window::HTMLMetaElementCtor DontEnum|DontDelete 0543 HTMLBaseElement Window::HTMLBaseElementCtor DontEnum|DontDelete 0544 HTMLIsIndexElement Window::HTMLIsIndexElementCtor DontEnum|DontDelete 0545 HTMLStyleElement Window::HTMLStyleElementCtor DontEnum|DontDelete 0546 HTMLBodyElement Window::HTMLBodyElementCtor DontEnum|DontDelete 0547 HTMLFormElement Window::HTMLFormElementCtor DontEnum|DontDelete 0548 HTMLSelectElement Window::HTMLSelectElementCtor DontEnum|DontDelete 0549 HTMLOptGroupElement Window::HTMLOptGroupElementCtor DontEnum|DontDelete 0550 HTMLOptionElement Window::HTMLOptionElementCtor DontEnum|DontDelete 0551 HTMLInputElement Window::HTMLInputElementCtor DontEnum|DontDelete 0552 HTMLTextAreaElement Window::HTMLTextAreaElementCtor DontEnum|DontDelete 0553 HTMLButtonElement Window::HTMLButtonElementCtor DontEnum|DontDelete 0554 HTMLLabelElement Window::HTMLLabelElementCtor DontEnum|DontDelete 0555 HTMLFieldSetElement Window::HTMLFieldSetElementCtor DontEnum|DontDelete 0556 HTMLLegendElement Window::HTMLLegendElementCtor DontEnum|DontDelete 0557 HTMLUListElement Window::HTMLUListElementCtor DontEnum|DontDelete 0558 HTMLOListElement Window::HTMLOListElementCtor DontEnum|DontDelete 0559 HTMLDListElement Window::HTMLDListElementCtor DontEnum|DontDelete 0560 HTMLDirectoryElement Window::HTMLDirectoryElementCtor DontEnum|DontDelete 0561 HTMLMenuElement Window::HTMLMenuElementCtor DontEnum|DontDelete 0562 HTMLLIElement Window::HTMLLIElementCtor DontEnum|DontDelete 0563 HTMLDivElement Window::HTMLDivElementCtor DontEnum|DontDelete 0564 HTMLParagraphElement Window::HTMLParagraphElementCtor DontEnum|DontDelete 0565 HTMLHeadingElement Window::HTMLHeadingElementCtor DontEnum|DontDelete 0566 HTMLBlockQuoteElement Window::HTMLBlockQuoteElementCtor DontEnum|DontDelete 0567 HTMLQuoteElement Window::HTMLQuoteElementCtor DontEnum|DontDelete 0568 HTMLPreElement Window::HTMLPreElementCtor DontEnum|DontDelete 0569 HTMLBRElement Window::HTMLBRElementCtor DontEnum|DontDelete 0570 HTMLBaseFontElement Window::HTMLBaseFontElementCtor DontEnum|DontDelete 0571 HTMLFontElement Window::HTMLFontElementCtor DontEnum|DontDelete 0572 HTMLHRElement Window::HTMLHRElementCtor DontEnum|DontDelete 0573 HTMLModElement Window::HTMLModElementCtor DontEnum|DontDelete 0574 HTMLAnchorElement Window::HTMLAnchorElementCtor DontEnum|DontDelete 0575 HTMLImageElement Window::HTMLImageElementCtor DontEnum|DontDelete 0576 HTMLObjectElement Window::HTMLObjectElementCtor DontEnum|DontDelete 0577 HTMLParamElement Window::HTMLParamElementCtor DontEnum|DontDelete 0578 HTMLAppletElement Window::HTMLAppletElementCtor DontEnum|DontDelete 0579 HTMLMapElement Window::HTMLMapElementCtor DontEnum|DontDelete 0580 HTMLAreaElement Window::HTMLAreaElementCtor DontEnum|DontDelete 0581 HTMLScriptElement Window::HTMLScriptElementCtor DontEnum|DontDelete 0582 HTMLTableElement Window::HTMLTableElementCtor DontEnum|DontDelete 0583 HTMLTableCaptionElement Window::HTMLTableCaptionElementCtor DontEnum|DontDelete 0584 HTMLTableColElement Window::HTMLTableColElementCtor DontEnum|DontDelete 0585 HTMLTableSectionElement Window::HTMLTableSectionElementCtor DontEnum|DontDelete 0586 HTMLTableRowElement Window::HTMLTableRowElementCtor DontEnum|DontDelete 0587 HTMLTableCellElement Window::HTMLTableCellElementCtor DontEnum|DontDelete 0588 HTMLFrameSetElement Window::HTMLFrameSetElementCtor DontEnum|DontDelete 0589 HTMLLayerElement Window::HTMLLayerElementCtor DontEnum|DontDelete 0590 HTMLFrameElement Window::HTMLFrameElementCtor DontEnum|DontDelete 0591 HTMLIFrameElement Window::HTMLIFrameElementCtor DontEnum|DontDelete 0592 HTMLCollection Window::HTMLCollectionCtor DontEnum|DontDelete 0593 HTMLCanvasElement Window::HTMLCanvasElementCtor DontEnum|DontDelete 0594 CSSStyleDeclaration Window::CSSStyleDeclarationCtor DontEnum|DontDelete 0595 StyleSheet Window::StyleSheetCtor DontEnum|DontDelete 0596 CanvasRenderingContext2D Window::Context2DCtor DontEnum|DontDelete 0597 SVGAngle Window::SVGAngleCtor DontEnum|DontDelete 0598 XPathResult Window::XPathResultCtor DontEnum|DontDelete 0599 XPathExpression Window::XPathExpressionCtor DontEnum|DontDelete 0600 XPathNSResolver Window::XPathNSResolverCtor DontEnum|DontDelete 0601 @end 0602 */ 0603 KJS_IMPLEMENT_PROTOFUNC(WindowFunc) 0604 0605 Window::Window(khtml::ChildFrame *p) 0606 : JSGlobalObject(/*no proto*/), m_frame(p), screen(nullptr), console(nullptr), history(nullptr), external(nullptr), loc(nullptr), m_evt(nullptr) 0607 { 0608 winq = new WindowQObject(this); 0609 //qCDebug(KHTML_LOG) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name(); 0610 } 0611 0612 Window::~Window() 0613 { 0614 qDeleteAll(m_delayed); 0615 delete winq; 0616 } 0617 0618 Window *Window::retrieveWindow(KParts::ReadOnlyPart *p) 0619 { 0620 JSObject *obj = retrieve(p)->getObject(); 0621 #ifndef NDEBUG 0622 // obj should never be null, except when javascript has been disabled in that part. 0623 KHTMLPart *part = qobject_cast<KHTMLPart *>(p); 0624 if (part && part->jScriptEnabled()) { 0625 assert(obj); 0626 assert(dynamic_cast<KJS::Window *>(obj)); // type checking 0627 } 0628 #endif 0629 if (!obj) { // JS disabled 0630 return nullptr; 0631 } 0632 return static_cast<KJS::Window *>(obj); 0633 } 0634 0635 Window *Window::retrieveActive(ExecState *exec) 0636 { 0637 JSValue *imp = exec->dynamicInterpreter()->globalObject(); 0638 assert(imp); 0639 assert(dynamic_cast<KJS::Window *>(imp)); 0640 return static_cast<KJS::Window *>(imp); 0641 } 0642 0643 JSValue *Window::retrieve(KParts::ReadOnlyPart *p) 0644 { 0645 assert(p); 0646 KHTMLPart *part = qobject_cast<KHTMLPart *>(p); 0647 KJSProxy *proxy = nullptr; 0648 if (!part) { 0649 part = qobject_cast<KHTMLPart *>(p->parent()); 0650 if (part) { 0651 proxy = part->framejScript(p); 0652 } 0653 } else { 0654 proxy = part->jScript(); 0655 } 0656 if (proxy) { 0657 #ifdef KJS_VERBOSE 0658 qCDebug(KHTML_LOG) << "Window::retrieve part=" << part << " '" << part->objectName() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject(); 0659 #endif 0660 return proxy->interpreter()->globalObject(); // the Global object is the "window" 0661 } else { 0662 #ifdef KJS_VERBOSE 0663 qCDebug(KHTML_LOG) << "Window::retrieve part=" << p << " '" << p->objectName() << "' no jsproxy."; 0664 #endif 0665 return jsUndefined(); // This can happen with JS disabled on the domain of that window 0666 } 0667 } 0668 0669 Location *Window::location() const 0670 { 0671 if (!loc) { 0672 const_cast<Window *>(this)->loc = new Location(m_frame); 0673 } 0674 return loc; 0675 } 0676 0677 // reference our special objects during garbage collection 0678 void Window::mark() 0679 { 0680 JSObject::mark(); 0681 if (screen && !screen->marked()) { 0682 screen->mark(); 0683 } 0684 if (console && !console->marked()) { 0685 console->mark(); 0686 } 0687 if (history && !history->marked()) { 0688 history->mark(); 0689 } 0690 if (external && !external->marked()) { 0691 external->mark(); 0692 } 0693 //qCDebug(KHTML_LOG) << "Window::mark " << this << " marking loc=" << loc; 0694 if (loc && !loc->marked()) { 0695 loc->mark(); 0696 } 0697 if (winq) { 0698 winq->mark(); 0699 } 0700 foreach (DelayedAction *action, m_delayed) { 0701 action->mark(); 0702 } 0703 } 0704 0705 UString Window::toString(ExecState *) const 0706 { 0707 return "[object Window]"; 0708 } 0709 0710 bool Window::isCrossFrameAccessible(int token) const 0711 { 0712 switch (token) { 0713 case Closed: 0714 case _Location: // No isSafeScript test here, we must be able to _set_ location.href (#49819) 0715 case _Window: 0716 case Self: 0717 case Frames: 0718 case Opener: 0719 case Parent: 0720 case Top: 0721 case Alert: 0722 case Confirm: 0723 case Prompt: 0724 case Open: 0725 case Close: 0726 case Focus: 0727 case Blur: 0728 case AToB: 0729 case BToA: 0730 case ValueOf: 0731 case ToString: 0732 case PostMessage: 0733 return true; 0734 default: 0735 return false; 0736 } 0737 } 0738 0739 bool Window::getOwnPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot) 0740 { 0741 #ifdef KJS_VERBOSE 0742 qCDebug(KHTML_LOG) << "Window(" << this << ")::getOwnPropertySlot " << propertyName.qstring(); 0743 #endif 0744 0745 // we want only limited operations on a closed window 0746 if (m_frame.isNull() || m_frame->m_part.isNull()) { 0747 const HashEntry *entry = Lookup::findEntry(&WindowTable, propertyName); 0748 if (entry) { 0749 switch (entry->value) { 0750 case Closed: 0751 case _Location: 0752 case ValueOf: 0753 case ToString: 0754 getSlotFromEntry<WindowFunc, Window>(entry, this, slot); 0755 return true; 0756 default: 0757 break; 0758 } 0759 } 0760 slot.setUndefined(this); 0761 return true; 0762 } 0763 0764 bool safe = isSafeScript(exec); 0765 0766 // Look for overrides first. 0767 JSValue **val = getDirectLocation(propertyName); 0768 if (val) { 0769 if (safe) { 0770 fillDirectLocationSlot(slot, val); 0771 } else { 0772 // We may need to permit access to the property map cross-frame in 0773 // order to pick up cross-frame accessible functions that got 0774 // cached as direct properties. 0775 const HashEntry *entry = Lookup::findEntry(&WindowTable, propertyName); 0776 if (entry && isCrossFrameAccessible(entry->value)) { 0777 fillDirectLocationSlot(slot, val); 0778 } else { 0779 slot.setUndefined(this); 0780 } 0781 } 0782 return true; 0783 } 0784 0785 // The only stuff we permit XSS (besides cached things above) are 0786 // a few of hashtable properties. 0787 const HashEntry *entry = Lookup::findEntry(&WindowTable, propertyName); 0788 if (!safe && (!entry || !isCrossFrameAccessible(entry->value))) { 0789 slot.setUndefined(this); 0790 return true; 0791 } 0792 0793 // invariant: accesses below this point are permitted by the XSS policy 0794 0795 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part.data()); 0796 0797 if (entry) { 0798 // Things that work on any ReadOnlyPart first 0799 switch (entry->value) { 0800 case Closed: 0801 case _Location: 0802 case _Window: 0803 case Self: 0804 getSlotFromEntry<WindowFunc, Window>(entry, this, slot); 0805 return true; 0806 default: 0807 break; 0808 } 0809 0810 if (!part) { 0811 slot.setUndefined(this); 0812 return true; 0813 } 0814 0815 // KHTMLPart-specific next. 0816 0817 // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses 0818 // if (navigate) to test for IE (unlikely). 0819 if (entry->value == Navigate && exec->dynamicInterpreter()->compatMode() == Interpreter::NetscapeCompat) { 0820 slot.setUndefined(this); 0821 return true; 0822 } 0823 0824 getSlotFromEntry<WindowFunc, Window>(entry, this, slot); 0825 return true; 0826 } 0827 0828 if (!part) { 0829 // not a KHTMLPart, so try to get plugin scripting stuff 0830 if (pluginRootGet(exec, m_frame->m_scriptable.data(), propertyName, slot)) { 0831 return true; 0832 } 0833 0834 slot.setUndefined(this); 0835 return true; 0836 } 0837 0838 // Now do frame indexing. 0839 KParts::ReadOnlyPart *rop = part->findFramePart(propertyName.qstring()); 0840 if (rop) { 0841 slot.setCustom(this, framePartGetter); 0842 return true; 0843 } 0844 0845 // allow window[1] or parent[1] etc. (#56983) 0846 bool ok; 0847 unsigned int i = propertyName.toArrayIndex(&ok); 0848 if (ok && frameByIndex(i)) { 0849 slot.setCustomIndex(this, i, indexGetterAdapter<Window>); 0850 return true; 0851 } 0852 0853 // allow shortcuts like 'Image1' instead of document.images.Image1 0854 DOM::DocumentImpl *doc = part->xmlDocImpl(); 0855 if (doc && doc->isHTMLDocument()) { 0856 DOM::ElementMappingCache::ItemInfo *info = doc->underDocNamedCache().get(propertyName.domString()); 0857 if (info || doc->getElementById(propertyName.domString())) { 0858 slot.setCustom(this, namedItemGetter); 0859 return true; 0860 } 0861 } 0862 0863 // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1 0864 // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping. 0865 #ifdef KJS_VERBOSE 0866 qCDebug(KHTML_LOG) << "WARNING: Window::get property not found: " << propertyName.qstring(); 0867 #endif 0868 0869 return JSObject::getOwnPropertySlot(exec, propertyName, slot); 0870 } 0871 0872 KParts::ReadOnlyPart *Window::frameByIndex(unsigned i) 0873 { 0874 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 0875 QList<KParts::ReadOnlyPart *> frames = part->frames(); 0876 unsigned int len = frames.count(); 0877 if (i < len) { 0878 KParts::ReadOnlyPart *frame = frames.at(i); 0879 return frame; 0880 } 0881 return nullptr; 0882 } 0883 0884 JSValue *Window::indexGetter(ExecState *exec, unsigned index) 0885 { 0886 Q_UNUSED(exec); 0887 KParts::ReadOnlyPart *frame = frameByIndex(index); 0888 if (frame) { 0889 return Window::retrieve(frame); 0890 } 0891 return jsUndefined(); //### ? 0892 } 0893 0894 JSValue *Window::framePartGetter(ExecState *exec, JSObject *, const Identifier &propertyName, const PropertySlot &slot) 0895 { 0896 Q_UNUSED(exec); 0897 Window *thisObj = static_cast<Window *>(slot.slotBase()); 0898 KHTMLPart *part = qobject_cast<KHTMLPart *>(thisObj->m_frame->m_part); 0899 KParts::ReadOnlyPart *rop = part->findFramePart(propertyName.qstring()); 0900 return thisObj->retrieve(rop); 0901 } 0902 0903 JSValue *Window::namedItemGetter(ExecState *exec, JSObject *, const Identifier &p, const PropertySlot &slot) 0904 { 0905 Window *thisObj = static_cast<Window *>(slot.slotBase()); 0906 KHTMLPart *part = qobject_cast<KHTMLPart *>(thisObj->m_frame->m_part); 0907 DOM::DocumentImpl *doc = part->xmlDocImpl(); 0908 0909 DOM::ElementMappingCache::ItemInfo *info = doc->underDocNamedCache().get(p.domString()); 0910 if (info) { 0911 if (info->nd) { 0912 return getDOMNode(exec, info->nd); 0913 } else { 0914 //No cached mapping, do it by hand... 0915 DOM::HTMLMappedNameCollectionImpl *coll = new DOM::HTMLMappedNameCollectionImpl(doc, 0916 DOM::HTMLCollectionImpl::DOCUMENT_NAMED_ITEMS, p.domString()); 0917 0918 if (coll->length() == 1) { 0919 info->nd = static_cast<DOM::ElementImpl *>(coll->firstItem()); 0920 delete coll; 0921 return getDOMNode(exec, info->nd); 0922 } 0923 return getHTMLCollection(exec, coll); 0924 } 0925 } 0926 0927 DOM::ElementImpl *element = doc->getElementById(p.domString()); 0928 return getDOMNode(exec, element); 0929 } 0930 0931 JSValue *Window::getValueProperty(ExecState *exec, int token) 0932 { 0933 KHTMLPart *part = m_frame.isNull() ? nullptr : qobject_cast<KHTMLPart *>(m_frame->m_part); 0934 if (!part) { 0935 switch (token) { 0936 case Closed: 0937 return jsBoolean(true); 0938 case _Location: 0939 return jsNull(); 0940 default: 0941 return jsUndefined(); 0942 } 0943 } 0944 0945 switch (token) { 0946 case Closed: 0947 return jsBoolean(!part); 0948 case _Location: 0949 // No isSafeScript test here, we must be able to _set_ location.href (#49819) 0950 return location(); 0951 case _Window: 0952 case Self: 0953 return retrieve(part); 0954 case Frames: 0955 return this; 0956 case Opener: 0957 if (!part->opener()) { 0958 return jsNull(); // ### a null Window might be better, but == null 0959 } else { // doesn't work yet 0960 return retrieve(part->opener()); 0961 } 0962 case Parent: 0963 return retrieve(part && part->parentPart() ? part->parentPart() : (KHTMLPart *)part); 0964 case Top: { 0965 KHTMLPart *p = part; 0966 while (p->parentPart()) { 0967 p = p->parentPart(); 0968 } 0969 return retrieve(p); 0970 } 0971 case Crypto: 0972 return jsUndefined(); // ### 0973 case DefaultStatus: 0974 return jsString(UString(part->jsDefaultStatusBarText())); 0975 case Status: 0976 return jsString(UString(part->jsStatusBarText())); 0977 case Document: 0978 return getDOMNode(exec, part->xmlDocImpl()); 0979 case FrameElement: 0980 if (m_frame->m_partContainerElement) { 0981 return getDOMNode(exec, m_frame->m_partContainerElement.data()); 0982 } else { 0983 return jsUndefined(); 0984 } 0985 case Node: 0986 return NodeConstructor::self(exec); 0987 case Range: 0988 return getRangeConstructor(exec); 0989 case NodeFilter: 0990 return getNodeFilterConstructor(exec); 0991 case NodeList: 0992 return NodeListPseudoCtor::self(exec); 0993 case DOMException: 0994 return getDOMExceptionConstructor(exec); 0995 case RangeException: 0996 return RangeExceptionPseudoCtor::self(exec); 0997 case CSSRule: 0998 return getCSSRuleConstructor(exec); 0999 case ElementCtor: 1000 return ElementPseudoCtor::self(exec); 1001 case DocumentFragmentCtor: 1002 return DocumentFragmentPseudoCtor::self(exec); 1003 case HTMLElementCtor: 1004 return HTMLElementPseudoCtor::self(exec); 1005 case HTMLHtmlElementCtor: 1006 return HTMLHtmlElementPseudoCtor::self(exec); 1007 case HTMLHeadElementCtor: 1008 return HTMLHeadElementPseudoCtor::self(exec); 1009 case HTMLLinkElementCtor: 1010 return HTMLLinkElementPseudoCtor::self(exec); 1011 case HTMLTitleElementCtor: 1012 return HTMLTitleElementPseudoCtor::self(exec); 1013 case HTMLMetaElementCtor: 1014 return HTMLMetaElementPseudoCtor::self(exec); 1015 case HTMLBaseElementCtor: 1016 return HTMLBaseElementPseudoCtor::self(exec); 1017 case HTMLIsIndexElementCtor: 1018 return HTMLIsIndexElementPseudoCtor::self(exec); 1019 case HTMLStyleElementCtor: 1020 return HTMLStyleElementPseudoCtor::self(exec); 1021 case HTMLBodyElementCtor: 1022 return HTMLBodyElementPseudoCtor::self(exec); 1023 case HTMLFormElementCtor: 1024 return HTMLFormElementPseudoCtor::self(exec); 1025 case HTMLSelectElementCtor: 1026 return HTMLSelectElementPseudoCtor::self(exec); 1027 case HTMLOptGroupElementCtor: 1028 return HTMLOptGroupElementPseudoCtor::self(exec); 1029 case HTMLOptionElementCtor: 1030 return HTMLOptionElementPseudoCtor::self(exec); 1031 case HTMLInputElementCtor: 1032 return HTMLInputElementPseudoCtor::self(exec); 1033 case HTMLTextAreaElementCtor: 1034 return HTMLTextAreaElementPseudoCtor::self(exec); 1035 case HTMLButtonElementCtor: 1036 return HTMLButtonElementPseudoCtor::self(exec); 1037 case HTMLLabelElementCtor: 1038 return HTMLLabelElementPseudoCtor::self(exec); 1039 case HTMLFieldSetElementCtor: 1040 return HTMLFieldSetElementPseudoCtor::self(exec); 1041 case HTMLLegendElementCtor: 1042 return HTMLLegendElementPseudoCtor::self(exec); 1043 case HTMLUListElementCtor: 1044 return HTMLUListElementPseudoCtor::self(exec); 1045 case HTMLOListElementCtor: 1046 return HTMLOListElementPseudoCtor::self(exec); 1047 case HTMLDListElementCtor: 1048 return HTMLDListElementPseudoCtor::self(exec); 1049 case HTMLDirectoryElementCtor: 1050 return HTMLDirectoryElementPseudoCtor::self(exec); 1051 case HTMLMenuElementCtor: 1052 return HTMLMenuElementPseudoCtor::self(exec); 1053 case HTMLLIElementCtor: 1054 return HTMLLIElementPseudoCtor::self(exec); 1055 case HTMLDivElementCtor: 1056 return HTMLDivElementPseudoCtor::self(exec); 1057 case HTMLParagraphElementCtor: 1058 return HTMLParagraphElementPseudoCtor::self(exec); 1059 case HTMLHeadingElementCtor: 1060 return HTMLHeadingElementPseudoCtor::self(exec); 1061 case HTMLBlockQuoteElementCtor: 1062 return HTMLBlockQuoteElementPseudoCtor::self(exec); 1063 case HTMLQuoteElementCtor: 1064 return HTMLQuoteElementPseudoCtor::self(exec); 1065 case HTMLPreElementCtor: 1066 return HTMLPreElementPseudoCtor::self(exec); 1067 case HTMLBRElementCtor: 1068 return HTMLBRElementPseudoCtor::self(exec); 1069 case HTMLBaseFontElementCtor: 1070 return HTMLBaseFontElementPseudoCtor::self(exec); 1071 case HTMLFontElementCtor: 1072 return HTMLFontElementPseudoCtor::self(exec); 1073 case HTMLHRElementCtor: 1074 return HTMLHRElementPseudoCtor::self(exec); 1075 case HTMLModElementCtor: 1076 return HTMLModElementPseudoCtor::self(exec); 1077 case HTMLAnchorElementCtor: 1078 return HTMLAnchorElementPseudoCtor::self(exec); 1079 case HTMLImageElementCtor: 1080 return HTMLImageElementPseudoCtor::self(exec); 1081 case HTMLObjectElementCtor: 1082 return HTMLObjectElementPseudoCtor::self(exec); 1083 case HTMLParamElementCtor: 1084 return HTMLParamElementPseudoCtor::self(exec); 1085 case HTMLAppletElementCtor: 1086 return HTMLAppletElementPseudoCtor::self(exec); 1087 case HTMLMapElementCtor: 1088 return HTMLMapElementPseudoCtor::self(exec); 1089 case HTMLAreaElementCtor: 1090 return HTMLAreaElementPseudoCtor::self(exec); 1091 case HTMLScriptElementCtor: 1092 return HTMLScriptElementPseudoCtor::self(exec); 1093 case HTMLTableElementCtor: 1094 return HTMLTableElementPseudoCtor::self(exec); 1095 case HTMLTableCaptionElementCtor: 1096 return HTMLTableCaptionElementPseudoCtor::self(exec); 1097 case HTMLTableColElementCtor: 1098 return HTMLTableColElementPseudoCtor::self(exec); 1099 case HTMLTableSectionElementCtor: 1100 return HTMLTableSectionElementPseudoCtor::self(exec); 1101 case HTMLTableRowElementCtor: 1102 return HTMLTableRowElementPseudoCtor::self(exec); 1103 case HTMLTableCellElementCtor: 1104 return HTMLTableCellElementPseudoCtor::self(exec); 1105 case HTMLFrameSetElementCtor: 1106 return HTMLFrameSetElementPseudoCtor::self(exec); 1107 case HTMLLayerElementCtor: 1108 return HTMLLayerElementPseudoCtor::self(exec); 1109 case HTMLFrameElementCtor: 1110 return HTMLFrameElementPseudoCtor::self(exec); 1111 case HTMLIFrameElementCtor: 1112 return HTMLIFrameElementPseudoCtor::self(exec); 1113 case HTMLCollectionCtor: 1114 return HTMLCollectionPseudoCtor::self(exec); 1115 case HTMLCanvasElementCtor: 1116 return HTMLCanvasElementPseudoCtor::self(exec); 1117 case Context2DCtor: 1118 return Context2DPseudoCtor::self(exec); 1119 case SVGAngleCtor: 1120 return SVGAnglePseudoCtor::self(exec); 1121 case XPathResultCtor: 1122 return XPathResultPseudoCtor::self(exec); 1123 case XPathExpressionCtor: 1124 return XPathExpressionPseudoCtor::self(exec); 1125 case XPathNSResolverCtor: 1126 return XPathNSResolverPseudoCtor::self(exec); 1127 case DocumentCtor: 1128 return DocumentPseudoCtor::self(exec); 1129 case HTMLDocumentCtor: 1130 return HTMLDocumentPseudoCtor::self(exec); 1131 case CSSStyleDeclarationCtor: 1132 return CSSStyleDeclarationPseudoCtor::self(exec); 1133 case StyleSheetCtor: 1134 return DOMStyleSheetPseudoCtor::self(exec); 1135 case EventCtor: 1136 return EventConstructor::self(exec); 1137 case MessageEventCtor: 1138 return MessageEventPseudoCtor::self(exec); 1139 case HashChangeEventCtor: 1140 return HashChangeEventPseudoCtor::self(exec); 1141 case MutationEventCtor: 1142 return getMutationEventConstructor(exec); 1143 case KeyboardEventCtor: 1144 return getKeyboardEventConstructor(exec); 1145 case EventExceptionCtor: 1146 return getEventExceptionConstructor(exec); 1147 case _History: 1148 return history ? history : 1149 (const_cast<Window *>(this)->history = new History(exec, part)); 1150 1151 case _External: 1152 return external ? external : 1153 (const_cast<Window *>(this)->external = new External(exec, part)); 1154 1155 case Event: 1156 if (m_evt) { 1157 return getDOMEvent(exec, m_evt); 1158 } else { 1159 #ifdef KJS_VERBOSE 1160 qCDebug(KHTML_LOG) << "WARNING: window(" << this << "," << part->objectName() << ").event, no event!"; 1161 #endif 1162 return jsUndefined(); 1163 } 1164 case InnerHeight: { 1165 if (!part->view()) { 1166 return jsUndefined(); 1167 } 1168 int ret = part->view()->visibleHeight(); 1169 // match Gecko which does not subtract the scrollbars 1170 if (part->view()->horizontalScrollBar()->isVisible()) { 1171 ret += part->view()->horizontalScrollBar()->sizeHint().height(); 1172 } 1173 return jsNumber(ret); 1174 } 1175 case InnerWidth: { 1176 if (!part->view()) { 1177 return jsUndefined(); 1178 } 1179 int ret = part->view()->visibleWidth(); 1180 // match Gecko which does not subtract the scrollbars 1181 if (part->view()->verticalScrollBar()->isVisible()) { 1182 ret += part->view()->verticalScrollBar()->sizeHint().width(); 1183 } 1184 return jsNumber(ret); 1185 } 1186 case Length: 1187 return jsNumber(part->frames().count()); 1188 case Name: 1189 return jsString(part->objectName()); 1190 case SideBar: 1191 return new MozillaSidebarExtension(exec, part); 1192 case _Navigator: 1193 case ClientInformation: { 1194 // Store the navigator in the object so we get the same one each time. 1195 JSValue *nav(new Navigator(exec, part)); 1196 const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete | ReadOnly | Internal); 1197 const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete | ReadOnly | Internal); 1198 return nav; 1199 } 1200 1201 case OffscreenBuffering: 1202 return jsBoolean(true); 1203 case OuterHeight: 1204 case OuterWidth: { 1205 #if HAVE_X11 && ! defined K_WS_QTONLY 1206 if (!part->widget()) { 1207 return jsNumber(0); 1208 } 1209 const KWindowInfo inf(part->widget()->topLevelWidget()->winId(), NET::WMGeometry); 1210 return jsNumber(token == OuterHeight ? 1211 inf.geometry().height() : inf.geometry().width()); 1212 #else 1213 return jsNumber(token == OuterHeight ? 1214 part->view()->height() : part->view()->width()); 1215 #endif 1216 } 1217 case PageXOffset: 1218 return jsNumber(part->view()->contentsX()); 1219 case PageYOffset: 1220 return jsNumber(part->view()->contentsY()); 1221 case Personalbar: 1222 return jsUndefined(); // ### 1223 case ScreenLeft: 1224 case ScreenX: { 1225 if (!part->view()) { 1226 return jsUndefined(); 1227 } 1228 QRect sg = QApplication::desktop()->screenGeometry(part->view()); 1229 return jsNumber(part->view()->mapToGlobal(QPoint(0, 0)).x() + sg.x()); 1230 } 1231 case ScreenTop: 1232 case ScreenY: { 1233 if (!part->view()) { 1234 return jsUndefined(); 1235 } 1236 QRect sg = QApplication::desktop()->screenGeometry(part->view()); 1237 return jsNumber(part->view()->mapToGlobal(QPoint(0, 0)).y() + sg.y()); 1238 } 1239 case ScrollX: { 1240 if (!part->view()) { 1241 return jsUndefined(); 1242 } 1243 return jsNumber(part->view()->contentsX()); 1244 } 1245 case ScrollY: { 1246 if (!part->view()) { 1247 return jsUndefined(); 1248 } 1249 return jsNumber(part->view()->contentsY()); 1250 } 1251 case Scrollbars: 1252 return new JSObject(); // ### 1253 case _Screen: 1254 return screen ? screen : 1255 (const_cast<Window *>(this)->screen = new Screen(exec)); 1256 case _Console: 1257 return console ? console : 1258 (const_cast<Window *>(this)->console = new Console(exec)); 1259 case Audio: 1260 return new AudioConstructorImp(exec, part->xmlDocImpl()); 1261 case Image: 1262 return new ImageConstructorImp(exec, part->xmlDocImpl()); 1263 case Option: 1264 return new OptionConstructorImp(exec, part->xmlDocImpl()); 1265 case XMLHttpRequest: 1266 return new XMLHttpRequestConstructorImp(exec, part->xmlDocImpl()); 1267 case XMLSerializer: 1268 return new XMLSerializerConstructorImp(exec); 1269 case DOMParser: 1270 return new DOMParserConstructorImp(exec, part->xmlDocImpl()); 1271 case ArrayBuffer: 1272 return new ArrayBufferConstructorImp(exec, part->xmlDocImpl()); 1273 case Int8Array: 1274 return new ArrayBufferConstructorImpInt8(exec, part->xmlDocImpl()); 1275 case Uint8Array: 1276 return new ArrayBufferConstructorImpUint8(exec, part->xmlDocImpl()); 1277 case Int16Array: 1278 return new ArrayBufferConstructorImpInt16(exec, part->xmlDocImpl()); 1279 case Uint16Array: 1280 return new ArrayBufferConstructorImpUint16(exec, part->xmlDocImpl()); 1281 case Int32Array: 1282 return new ArrayBufferConstructorImpInt32(exec, part->xmlDocImpl()); 1283 case Uint32Array: 1284 return new ArrayBufferConstructorImpUint32(exec, part->xmlDocImpl()); 1285 case Float32Array: 1286 return new ArrayBufferConstructorImpFloat32(exec, part->xmlDocImpl()); 1287 case Float64Array: 1288 return new ArrayBufferConstructorImpFloat64(exec, part->xmlDocImpl()); 1289 case Onabort: 1290 return getListener(exec, DOM::EventImpl::ABORT_EVENT); 1291 case Onblur: 1292 return getListener(exec, DOM::EventImpl::BLUR_EVENT); 1293 case Onchange: 1294 return getListener(exec, DOM::EventImpl::CHANGE_EVENT); 1295 case Onclick: 1296 return getListener(exec, DOM::EventImpl::KHTML_ECMA_CLICK_EVENT); 1297 case Ondblclick: 1298 return getListener(exec, DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT); 1299 case Ondragdrop: 1300 return getListener(exec, DOM::EventImpl::KHTML_DRAGDROP_EVENT); 1301 case Onerror: 1302 return getListener(exec, DOM::EventImpl::ERROR_EVENT); 1303 case Onfocus: 1304 return getListener(exec, DOM::EventImpl::FOCUS_EVENT); 1305 case Onkeydown: 1306 return getListener(exec, DOM::EventImpl::KEYDOWN_EVENT); 1307 case Onkeypress: 1308 return getListener(exec, DOM::EventImpl::KEYPRESS_EVENT); 1309 case Onkeyup: 1310 return getListener(exec, DOM::EventImpl::KEYUP_EVENT); 1311 case Onload: 1312 return getListener(exec, DOM::EventImpl::LOAD_EVENT); 1313 case Onmessage: 1314 return getListener(exec, DOM::EventImpl::MESSAGE_EVENT); 1315 case Onmousedown: 1316 return getListener(exec, DOM::EventImpl::MOUSEDOWN_EVENT); 1317 case Onmousemove: 1318 return getListener(exec, DOM::EventImpl::MOUSEMOVE_EVENT); 1319 case Onmouseout: 1320 return getListener(exec, DOM::EventImpl::MOUSEOUT_EVENT); 1321 case Onmouseover: 1322 return getListener(exec, DOM::EventImpl::MOUSEOVER_EVENT); 1323 case Onmouseup: 1324 return getListener(exec, DOM::EventImpl::MOUSEUP_EVENT); 1325 case Onmove: 1326 return getListener(exec, DOM::EventImpl::KHTML_MOVE_EVENT); 1327 case Onreset: 1328 return getListener(exec, DOM::EventImpl::RESET_EVENT); 1329 case Onresize: 1330 return getListener(exec, DOM::EventImpl::RESIZE_EVENT); 1331 case Onscroll: 1332 return getListener(exec, DOM::EventImpl::SCROLL_EVENT); 1333 case Onselect: 1334 return getListener(exec, DOM::EventImpl::SELECT_EVENT); 1335 case Onsubmit: 1336 return getListener(exec, DOM::EventImpl::SUBMIT_EVENT); 1337 case Onunload: 1338 return getListener(exec, DOM::EventImpl::UNLOAD_EVENT); 1339 case Onhashchange: 1340 return getListener(exec, DOM::EventImpl::HASHCHANGE_EVENT); 1341 } 1342 1343 return jsUndefined(); 1344 } 1345 1346 void Window::put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr) 1347 { 1348 // we don't want any operations on a closed window 1349 if (m_frame.isNull() || m_frame->m_part.isNull()) { 1350 // ### throw exception? allow setting of some props like location? 1351 return; 1352 } 1353 1354 // Called by an internal KJS call (e.g. InterpreterImp's constructor) ? 1355 // If yes, save time and jump directly to JSObject. We also have 1356 // to do this now since calling isSafeScript() may not work yet. 1357 if (attr != None && attr != DontDelete) { 1358 JSObject::put(exec, propertyName, value, attr); 1359 return; 1360 } 1361 1362 // If we already have a variable, that's writeable w/o a getter/setter mess, just write to it. 1363 bool safe = isSafeScript(exec); 1364 if (safe) { 1365 if (JSValue **slot = getDirectWriteLocation(propertyName)) { 1366 *slot = value; 1367 return; 1368 } 1369 } 1370 1371 const HashEntry *entry = Lookup::findEntry(&WindowTable, propertyName); 1372 if (entry) { 1373 #ifdef KJS_VERBOSE 1374 qCDebug(KHTML_LOG) << "Window(" << this << ")::put " << propertyName.qstring(); 1375 #endif 1376 if (entry->value == _Location) { 1377 goURL(exec, value->toString(exec).qstring()); 1378 return; 1379 } 1380 1381 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1382 if (part) { 1383 switch (entry->value) { 1384 case Status: { 1385 if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host()) 1386 == KHTMLSettings::KJSWindowStatusAllow) { 1387 UString s = value->toString(exec); 1388 part->setJSStatusBarText(s.qstring()); 1389 } 1390 return; 1391 } 1392 case DefaultStatus: { 1393 if (isSafeScript(exec) && part->settings()->windowStatusPolicy(part->url().host()) 1394 == KHTMLSettings::KJSWindowStatusAllow) { 1395 UString s = value->toString(exec); 1396 part->setJSDefaultStatusBarText(s.qstring()); 1397 } 1398 return; 1399 } 1400 case Onabort: 1401 if (isSafeScript(exec)) { 1402 setListener(exec, DOM::EventImpl::ABORT_EVENT, value); 1403 } 1404 return; 1405 case Onblur: 1406 if (isSafeScript(exec)) { 1407 setListener(exec, DOM::EventImpl::BLUR_EVENT, value); 1408 } 1409 return; 1410 case Onchange: 1411 if (isSafeScript(exec)) { 1412 setListener(exec, DOM::EventImpl::CHANGE_EVENT, value); 1413 } 1414 return; 1415 case Onclick: 1416 if (isSafeScript(exec)) { 1417 setListener(exec, DOM::EventImpl::KHTML_ECMA_CLICK_EVENT, value); 1418 } 1419 return; 1420 case Ondblclick: 1421 if (isSafeScript(exec)) { 1422 setListener(exec, DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT, value); 1423 } 1424 return; 1425 case Ondragdrop: 1426 if (isSafeScript(exec)) { 1427 setListener(exec, DOM::EventImpl::KHTML_DRAGDROP_EVENT, value); 1428 } 1429 return; 1430 case Onerror: 1431 if (isSafeScript(exec)) { 1432 setListener(exec, DOM::EventImpl::ERROR_EVENT, value); 1433 } 1434 return; 1435 case Onfocus: 1436 if (isSafeScript(exec)) { 1437 setListener(exec, DOM::EventImpl::FOCUS_EVENT, value); 1438 } 1439 return; 1440 case Onkeydown: 1441 if (isSafeScript(exec)) { 1442 setListener(exec, DOM::EventImpl::KEYDOWN_EVENT, value); 1443 } 1444 return; 1445 case Onkeypress: 1446 if (isSafeScript(exec)) { 1447 setListener(exec, DOM::EventImpl::KEYPRESS_EVENT, value); 1448 } 1449 return; 1450 case Onkeyup: 1451 if (isSafeScript(exec)) { 1452 setListener(exec, DOM::EventImpl::KEYUP_EVENT, value); 1453 } 1454 return; 1455 case Onload: 1456 if (isSafeScript(exec)) { 1457 setListener(exec, DOM::EventImpl::LOAD_EVENT, value); 1458 } 1459 return; 1460 case Onmessage: 1461 if (isSafeScript(exec)) { 1462 setListener(exec, DOM::EventImpl::MESSAGE_EVENT, value); 1463 } 1464 return; 1465 case Onmousedown: 1466 if (isSafeScript(exec)) { 1467 setListener(exec, DOM::EventImpl::MOUSEDOWN_EVENT, value); 1468 } 1469 return; 1470 case Onmousemove: 1471 if (isSafeScript(exec)) { 1472 setListener(exec, DOM::EventImpl::MOUSEMOVE_EVENT, value); 1473 } 1474 return; 1475 case Onmouseout: 1476 if (isSafeScript(exec)) { 1477 setListener(exec, DOM::EventImpl::MOUSEOUT_EVENT, value); 1478 } 1479 return; 1480 case Onmouseover: 1481 if (isSafeScript(exec)) { 1482 setListener(exec, DOM::EventImpl::MOUSEOVER_EVENT, value); 1483 } 1484 return; 1485 case Onmouseup: 1486 if (isSafeScript(exec)) { 1487 setListener(exec, DOM::EventImpl::MOUSEUP_EVENT, value); 1488 } 1489 return; 1490 case Onmove: 1491 if (isSafeScript(exec)) { 1492 setListener(exec, DOM::EventImpl::KHTML_MOVE_EVENT, value); 1493 } 1494 return; 1495 case Onreset: 1496 if (isSafeScript(exec)) { 1497 setListener(exec, DOM::EventImpl::RESET_EVENT, value); 1498 } 1499 return; 1500 case Onresize: 1501 if (isSafeScript(exec)) { 1502 setListener(exec, DOM::EventImpl::RESIZE_EVENT, value); 1503 } 1504 return; 1505 case Onscroll: 1506 if (isSafeScript(exec)) { 1507 setListener(exec, DOM::EventImpl::SCROLL_EVENT, value); 1508 } 1509 return; 1510 case Onselect: 1511 if (isSafeScript(exec)) { 1512 setListener(exec, DOM::EventImpl::SELECT_EVENT, value); 1513 } 1514 return; 1515 case Onsubmit: 1516 if (isSafeScript(exec)) { 1517 setListener(exec, DOM::EventImpl::SUBMIT_EVENT, value); 1518 } 1519 return; 1520 case Onunload: 1521 if (isSafeScript(exec)) { 1522 setListener(exec, DOM::EventImpl::UNLOAD_EVENT, value); 1523 } 1524 return; 1525 case Onhashchange: 1526 if (isSafeScript(exec)) { 1527 setListener(exec, DOM::EventImpl::HASHCHANGE_EVENT, value); 1528 } 1529 return; 1530 case Name: 1531 if (isSafeScript(exec)) { 1532 part->setObjectName(value->toString(exec).qstring().toLocal8Bit().data()); 1533 } 1534 return; 1535 default: 1536 break; 1537 } 1538 } 1539 } 1540 if (isSafeScript(exec) && 1541 pluginRootPut(exec, m_frame->m_scriptable.data(), propertyName, value)) { 1542 return; 1543 } 1544 if (safe) { 1545 //qCDebug(KHTML_LOG) << "Window("<<this<<")::put storing " << propertyName.qstring(); 1546 JSObject::put(exec, propertyName, value, attr); 1547 } 1548 } 1549 1550 bool Window::toBoolean(ExecState *) const 1551 { 1552 return !m_frame.isNull() && !m_frame->m_part.isNull(); 1553 } 1554 1555 DOM::AbstractViewImpl *Window::toAbstractView() const 1556 { 1557 KHTMLPart *part = ::qobject_cast<KHTMLPart *>(m_frame->m_part); 1558 if (!part || !part->xmlDocImpl()) { 1559 return nullptr; 1560 } 1561 return part->xmlDocImpl()->defaultView(); 1562 } 1563 1564 void Window::scheduleClose() 1565 { 1566 // qCDebug(KHTML_LOG) << "Window::scheduleClose window.close() " << m_frame; 1567 Q_ASSERT(winq); 1568 QTimer::singleShot(0, winq, SLOT(timeoutClose())); 1569 } 1570 1571 void Window::closeNow() 1572 { 1573 if (m_frame.isNull() || m_frame->m_part.isNull()) { 1574 // qCDebug(KHTML_LOG) << "part is deleted already"; 1575 } else { 1576 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1577 if (!part) { 1578 // qCDebug(KHTML_LOG) << "closeNow on non KHTML part"; 1579 } else { 1580 //qCDebug(KHTML_LOG) << " -> closing window"; 1581 // We want to make sure that window.open won't find this part by name. 1582 part->setObjectName(QString()); 1583 part->deleteLater(); 1584 part = nullptr; 1585 } 1586 } 1587 } 1588 1589 void Window::afterScriptExecution() 1590 { 1591 DOM::DocumentImpl::updateDocumentsRendering(); 1592 const QList<DelayedAction *> delayedActions = m_delayed; 1593 m_delayed.clear(); 1594 foreach (DelayedAction *act, delayedActions) { 1595 if (!act->execute(this)) { 1596 break; // done with them 1597 } 1598 } 1599 qDeleteAll(delayedActions); 1600 } 1601 1602 bool Window::checkIsSafeScript(KParts::ReadOnlyPart *activePart) const 1603 { 1604 if (m_frame.isNull() || m_frame->m_part.isNull()) { // part deleted ? can't grant access 1605 // qCDebug(KHTML_LOG) << "Window::isSafeScript: accessing deleted part !"; 1606 return false; 1607 } 1608 if (!activePart) { 1609 // qCDebug(KHTML_LOG) << "Window::isSafeScript: current interpreter's part is 0L!"; 1610 return false; 1611 } 1612 if (activePart == m_frame->m_part) { // Not calling from another frame, no problem. 1613 return true; 1614 } 1615 1616 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1617 if (!part) { 1618 return true; // not a KHTMLPart 1619 } 1620 1621 if (!part->xmlDocImpl()) { 1622 return true; // allow to access a window that was just created (e.g. with window.open("about:blank")) 1623 } 1624 1625 DOM::DocumentImpl *thisDocument = part->xmlDocImpl(); 1626 1627 KHTMLPart *activeKHTMLPart = qobject_cast<KHTMLPart *>(activePart); 1628 if (!activeKHTMLPart) { 1629 return true; // not a KHTMLPart 1630 } 1631 1632 DOM::DocumentImpl *actDocument = activeKHTMLPart->xmlDocImpl(); 1633 if (!actDocument) { 1634 // qCDebug(KHTML_LOG) << "Window::isSafeScript: active part has no document!"; 1635 return false; 1636 } 1637 khtml::SecurityOrigin *actDomain = actDocument->origin(); 1638 khtml::SecurityOrigin *thisDomain = thisDocument->origin(); 1639 1640 if (actDomain->canAccess(thisDomain)) { 1641 #ifdef KJS_VERBOSE 1642 qCDebug(KHTML_LOG) << "JavaScript: access granted, domain is '" << actDomain.string() << "'"; 1643 #endif 1644 return true; 1645 } 1646 1647 // qCDebug(KHTML_LOG) << "WARNING: JavaScript: access denied for current frame '" << actDomain->toString() << "' to frame '" << thisDomain->toString() << "'"; 1648 // TODO after 3.1: throw security exception (exec->setException()) 1649 return false; 1650 } 1651 1652 void Window::setListener(ExecState *exec, int eventId, JSValue *func) 1653 { 1654 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1655 if (!part || !isSafeScript(exec)) { 1656 return; 1657 } 1658 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(part->htmlDocument().handle()); 1659 if (!doc) { 1660 return; 1661 } 1662 1663 doc->setHTMLWindowEventListener(eventId, getJSEventListener(func, true)); 1664 } 1665 1666 JSValue *Window::getListener(ExecState *exec, int eventId) const 1667 { 1668 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1669 if (!part || !isSafeScript(exec)) { 1670 return jsUndefined(); 1671 } 1672 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl *>(part->htmlDocument().handle()); 1673 if (!doc) { 1674 return jsUndefined(); 1675 } 1676 1677 DOM::EventListener *listener = doc->getHTMLWindowEventListener(eventId); 1678 if (listener && static_cast<JSEventListener *>(listener)->listenerObj()) { 1679 return static_cast<JSEventListener *>(listener)->listenerObj(); 1680 } else { 1681 return jsNull(); 1682 } 1683 } 1684 1685 JSEventListener *Window::getJSEventListener(JSValue *val, bool html) 1686 { 1687 // This function is so hot that it's worth coding it directly with imps. 1688 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1689 if (!part || val->type() != ObjectType) { 1690 return nullptr; 1691 } 1692 1693 // It's ObjectType, so it must be valid. 1694 JSObject *listenerObject = val->getObject(); 1695 JSObject *thisObject = listenerObject; 1696 1697 // 'listener' is not a simple ecma function. (Always use sanity checks: Better safe than sorry!) 1698 if (!listenerObject->implementsCall() && part && part->jScript() && part->jScript()->interpreter()) { 1699 Interpreter *interpreter = part->jScript()->interpreter(); 1700 1701 // 'listener' probably is an EventListener object containing a 'handleEvent' function. 1702 JSValue *handleEventValue = listenerObject->get(interpreter->globalExec(), Identifier("handleEvent")); 1703 JSObject *handleEventObject = handleEventValue->getObject(); 1704 1705 if (handleEventObject && handleEventObject->implementsCall()) { 1706 thisObject = listenerObject; 1707 listenerObject = handleEventObject; 1708 } 1709 } 1710 1711 JSEventListener *existingListener = jsEventListeners.value(QPair<void *, bool>(thisObject, html)); 1712 if (existingListener) { 1713 assert(existingListener->isHTMLEventListener() == html); 1714 return existingListener; 1715 } 1716 1717 // Note that the JSEventListener constructor adds it to our jsEventListeners list 1718 return new JSEventListener(listenerObject, thisObject, this, html); 1719 } 1720 1721 JSLazyEventListener *Window::getJSLazyEventListener(const QString &code, const QString &srcUrl, int line, 1722 const QString &name, DOM::NodeImpl *node, bool svg) 1723 { 1724 return new JSLazyEventListener(code, srcUrl, line, name, this, node, svg); 1725 } 1726 1727 void Window::clear(ExecState *exec) 1728 { 1729 Q_UNUSED(exec); 1730 delete winq; 1731 qDeleteAll(m_delayed); 1732 m_delayed.clear(); 1733 1734 winq = nullptr; 1735 // Get rid of everything, those user vars could hold references to DOM nodes 1736 clearProperties(); 1737 1738 // Ditto for the special subobjects. 1739 screen = nullptr; 1740 console = nullptr; 1741 history = nullptr; 1742 external = nullptr; 1743 loc = nullptr; 1744 setPrototype(jsNull()); 1745 1746 // Break the dependency between the listeners and their object 1747 QHashIterator<const QPair<void *, bool>, JSEventListener *> it(jsEventListeners); 1748 while (it.hasNext()) { 1749 it.next(); 1750 it.value()->clear(); 1751 } 1752 1753 // Forget about the listeners (the DOM::NodeImpls will delete them) 1754 jsEventListeners.clear(); 1755 1756 if (m_frame) { 1757 KJSProxy *proxy = m_frame->m_jscript; 1758 if (proxy) { // i.e. JS not disabled 1759 winq = new WindowQObject(this); 1760 // Now recreate a working global object for the next URL that will use us 1761 KJS::Interpreter *interpreter = proxy->interpreter(); 1762 interpreter->initGlobalObject(); 1763 } 1764 } 1765 } 1766 1767 void Window::setCurrentEvent(DOM::EventImpl *evt) 1768 { 1769 m_evt = evt; 1770 //qCDebug(KHTML_LOG) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt; 1771 } 1772 1773 void Window::goURL(ExecState *exec, const QString &url, bool lockHistory) 1774 { 1775 Window *active = Window::retrieveActive(exec); 1776 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1777 KHTMLPart *active_part = qobject_cast<KHTMLPart *>(active->part()); 1778 // Complete the URL using the "active part" (running interpreter) 1779 if (active_part && part) { 1780 QString dstUrl = active_part->htmlDocument().completeURL(url).string(); 1781 // qCDebug(KHTML_LOG) << "Window::goURL dstUrl=" << dstUrl; 1782 1783 // check if we're allowed to inject javascript 1784 if (!KHTMLPartPrivate::isJavaScriptURL(dstUrl) || isSafeScript(exec)) { 1785 part->scheduleRedirection(-1, dstUrl, lockHistory); 1786 } 1787 } else if (!part && m_frame->m_partContainerElement) { 1788 KParts::BrowserExtension *b = KParts::BrowserExtension::childObject(m_frame->m_part); 1789 if (b) { 1790 emit b->openUrlRequest(QUrl(m_frame->m_partContainerElement.data()->document()->completeURL(url))); 1791 } 1792 // qCDebug(KHTML_LOG) << "goURL for ROPart"; 1793 } 1794 } 1795 1796 class DelayedGoHistory: public Window::DelayedAction 1797 { 1798 public: 1799 DelayedGoHistory(int _steps): steps(_steps) 1800 {} 1801 1802 bool execute(Window *win) override 1803 { 1804 win->goHistory(steps); 1805 return true; 1806 } 1807 private: 1808 int steps; 1809 }; 1810 1811 void Window::delayedGoHistory(int steps) 1812 { 1813 m_delayed.append(new DelayedGoHistory(steps)); 1814 } 1815 1816 void Window::goHistory(int steps) 1817 { 1818 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1819 if (!part) 1820 // TODO history readonlypart 1821 { 1822 return; 1823 } 1824 KParts::BrowserExtension *ext = part->browserExtension(); 1825 if (!ext) { 1826 return; 1827 } 1828 KParts::BrowserInterface *iface = ext->browserInterface(); 1829 1830 if (!iface) { 1831 return; 1832 } 1833 1834 iface->callMethod("goHistory", steps); 1835 //emit ext->goHistory(steps); 1836 } 1837 1838 void KJS::Window::resizeTo(QWidget *tl, int width, int height) 1839 { 1840 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1841 if (!part) 1842 // TODO resizeTo readonlypart 1843 { 1844 return; 1845 } 1846 KParts::BrowserExtension *ext = part->browserExtension(); 1847 if (!ext) { 1848 // qCDebug(KHTML_LOG) << "Window::resizeTo found no browserExtension"; 1849 return; 1850 } 1851 1852 // Security check: within desktop limits and bigger than 100x100 (per spec) 1853 if (width < 100 || height < 100) { 1854 // qCDebug(KHTML_LOG) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")"; 1855 return; 1856 } 1857 1858 QRect sg = QApplication::desktop()->screenGeometry(tl); 1859 1860 if (width > sg.width() || height > sg.height()) { 1861 // qCDebug(KHTML_LOG) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")"; 1862 return; 1863 } 1864 1865 // qCDebug(KHTML_LOG) << "resizing to " << width << "x" << height; 1866 1867 emit ext->resizeTopLevelWidget(width, height); 1868 1869 // If the window is out of the desktop, move it up/left 1870 // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker) 1871 int right = tl->x() + tl->frameGeometry().width(); 1872 int bottom = tl->y() + tl->frameGeometry().height(); 1873 int moveByX = 0; 1874 int moveByY = 0; 1875 if (right > sg.right()) { 1876 moveByX = - right + sg.right(); // always <0 1877 } 1878 if (bottom > sg.bottom()) { 1879 moveByY = - bottom + sg.bottom(); // always <0 1880 } 1881 if (moveByX || moveByY) { 1882 emit ext->moveTopLevelWidget(tl->x() + moveByX, tl->y() + moveByY); 1883 } 1884 } 1885 1886 bool Window::targetIsExistingWindow(KHTMLPart *ourPart, const QString &frameName) 1887 { 1888 QString normalized = frameName.toLower(); 1889 if (normalized == "_top" || normalized == "_self" || normalized == "_parent") { 1890 return true; 1891 } 1892 1893 // Find the highest parent part we can access. 1894 KHTMLPart *p = ourPart; 1895 while (p->parentPart() && p->parentPart()->checkFrameAccess(ourPart)) { 1896 p = p->parentPart(); 1897 } 1898 1899 return p->findFrame(frameName); 1900 } 1901 1902 JSValue *Window::openWindow(ExecState *exec, const List &args) 1903 { 1904 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 1905 if (!part) { 1906 return jsUndefined(); 1907 } 1908 KHTMLView *widget = part->view(); 1909 JSValue *v = args[0]; 1910 QString str; 1911 if (!v->isUndefinedOrNull()) { 1912 str = v->toString(exec).qstring(); 1913 } 1914 1915 // prepare arguments 1916 QUrl url; 1917 if (!str.isEmpty()) { 1918 KHTMLPart *p = qobject_cast<KHTMLPart *>(Window::retrieveActive(exec)->m_frame->m_part); 1919 if (p) { 1920 url = QUrl(p->htmlDocument().completeURL(str).string()); 1921 } 1922 if (!p || 1923 !static_cast<DOM::DocumentImpl *>(p->htmlDocument().handle())->isURLAllowed(url.url())) { 1924 return jsUndefined(); 1925 } 1926 } 1927 1928 KHTMLSettings::KJSWindowOpenPolicy policy = 1929 part->settings()->windowOpenPolicy(part->url().host()); 1930 1931 QString frameName = args.size() > 1 ? args[1]->toString(exec).qstring() : QString("_blank"); 1932 1933 // Always permit opening in an exist frame (including _self, etc.) 1934 if (targetIsExistingWindow(part, frameName)) { 1935 policy = KHTMLSettings::KJSWindowOpenAllow; 1936 } 1937 1938 if (policy == KHTMLSettings::KJSWindowOpenAsk) { 1939 emit part->browserExtension()->requestFocus(part); 1940 QString caption; 1941 if (!part->url().host().isEmpty()) { 1942 caption = part->url().host() + " - "; 1943 } 1944 caption += i18n("Confirmation: JavaScript Popup"); 1945 if (KMessageBox::questionTwoActions(widget, 1946 str.isEmpty() ? 1947 i18n("This site is requesting to open up a new browser " 1948 "window via JavaScript.\n" 1949 "Do you want to allow this?") : 1950 i18n("<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />" 1951 "Do you want to allow this?</qt>", KStringHandler::csqueeze(url.toDisplayString().toHtmlEscaped(), 100)), 1952 caption, KGuiItem(i18n("Allow")), KGuiItem(i18n("Do Not Allow"))) == KMessageBox::PrimaryAction) { 1953 policy = KHTMLSettings::KJSWindowOpenAllow; 1954 } 1955 } else if (policy == KHTMLSettings::KJSWindowOpenSmart) { 1956 // window.open disabled unless from a key/mouse event 1957 if (static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->isWindowOpenAllowed()) { 1958 policy = KHTMLSettings::KJSWindowOpenAllow; 1959 } 1960 } 1961 1962 v = args[2]; 1963 QString features; 1964 if (v && v->type() != UndefinedType && v->toString(exec).size() > 0) { 1965 features = v->toString(exec).qstring(); 1966 // Buggy scripts have ' at beginning and end, cut those 1967 if (features.startsWith(QLatin1Char('\'')) && 1968 features.endsWith(QLatin1Char('\''))) { 1969 features = features.mid(1, features.length() - 2); 1970 } 1971 } 1972 1973 if (policy != KHTMLSettings::KJSWindowOpenAllow) { 1974 if (url.isEmpty()) { 1975 part->setSuppressedPopupIndicator(true, nullptr); 1976 } else { 1977 part->setSuppressedPopupIndicator(true, part); 1978 m_suppressedWindowInfo.append(SuppressedWindowInfo(url, frameName, features)); 1979 } 1980 return jsUndefined(); 1981 } else { 1982 return executeOpenWindow(exec, url, frameName, features); 1983 } 1984 } 1985 1986 JSValue *Window::executeOpenWindow(ExecState *exec, const QUrl &url, const QString &frameName, const QString &features) 1987 { 1988 KHTMLPart *p = qobject_cast<KHTMLPart *>(m_frame->m_part); 1989 KHTMLView *widget = p->view(); 1990 KParts::WindowArgs winargs; 1991 1992 // Split on commas and syntactic whitespace 1993 // Testcase: 'height=600, width=950 left = 30,top = 50,statusbar=0' 1994 static const QRegExp m(",|\\b\\s+(?!=)"); 1995 1996 // scan feature argument 1997 if (!features.isEmpty()) { 1998 // specifying window params means false defaults 1999 winargs.setMenuBarVisible(false); 2000 winargs.setToolBarsVisible(false); 2001 winargs.setStatusBarVisible(false); 2002 winargs.setScrollBarsVisible(false); 2003 const QStringList flist = features.trimmed().split(m); 2004 QStringList::ConstIterator it = flist.begin(); 2005 while (it != flist.end()) { 2006 QString s = *it++; 2007 QString key, val; 2008 int pos = s.indexOf('='); 2009 if (pos >= 0) { 2010 key = s.left(pos).trimmed().toLower(); 2011 val = s.mid(pos + 1).trimmed().toLower(); 2012 QRect screen = QApplication::desktop()->screenGeometry(widget->topLevelWidget()); 2013 2014 if (key == "left" || key == "screenx") { 2015 winargs.setX((int)val.toFloat() + screen.x()); 2016 if (winargs.x() < screen.x() || winargs.x() > screen.right()) { 2017 winargs.setX(screen.x()); // only safe choice until size is determined 2018 } 2019 } else if (key == "top" || key == "screeny") { 2020 winargs.setY((int)val.toFloat() + screen.y()); 2021 if (winargs.y() < screen.y() || winargs.y() > screen.bottom()) { 2022 winargs.setY(screen.y()); // only safe choice until size is determined 2023 } 2024 } else if (key == "height") { 2025 winargs.setHeight((int)val.toFloat() + 2 * qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) + 2); 2026 if (winargs.height() > screen.height()) { // should actually check workspace 2027 winargs.setHeight(screen.height()); 2028 } 2029 if (winargs.height() < 100) { 2030 winargs.setHeight(100); 2031 } 2032 } else if (key == "width") { 2033 winargs.setWidth((int)val.toFloat() + 2 * qApp->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) + 2); 2034 if (winargs.width() > screen.width()) { // should actually check workspace 2035 winargs.setWidth(screen.width()); 2036 } 2037 if (winargs.width() < 100) { 2038 winargs.setWidth(100); 2039 } 2040 } else { 2041 goto boolargs; 2042 } 2043 continue; 2044 } else { 2045 // leaving away the value gives true 2046 key = s.trimmed().toLower(); 2047 val = "1"; 2048 } 2049 boolargs: 2050 if (key == "menubar") { 2051 winargs.setMenuBarVisible(val == "1" || val == "yes"); 2052 } else if (key == "toolbar") { 2053 winargs.setToolBarsVisible(val == "1" || val == "yes"); 2054 } else if (key == "location") { // ### missing in WindowArgs 2055 winargs.setToolBarsVisible(val == "1" || val == "yes"); 2056 } else if (key == "status" || key == "statusbar") { 2057 winargs.setStatusBarVisible(val == "1" || val == "yes"); 2058 } else if (key == "scrollbars") { 2059 winargs.setScrollBarsVisible(val == "1" || val == "yes"); 2060 } else if (key == "resizable") { 2061 winargs.setResizable(val == "1" || val == "yes"); 2062 } else if (key == "fullscreen") { 2063 winargs.setFullScreen(val == "1" || val == "yes"); 2064 } 2065 } 2066 } 2067 2068 KParts::OpenUrlArguments args; 2069 KParts::BrowserArguments browserArgs; 2070 browserArgs.frameName = frameName; 2071 2072 if (browserArgs.frameName.toLower() == "_top") { 2073 while (p->parentPart()) { 2074 p = p->parentPart(); 2075 } 2076 Window::retrieveWindow(p)->goURL(exec, url.url()); 2077 return Window::retrieve(p); 2078 } 2079 if (browserArgs.frameName.toLower() == "_parent") { 2080 if (p->parentPart()) { 2081 p = p->parentPart(); 2082 } 2083 Window::retrieveWindow(p)->goURL(exec, url.url()); 2084 return Window::retrieve(p); 2085 } 2086 if (browserArgs.frameName.toLower() == "_self") { 2087 Window::retrieveWindow(p)->goURL(exec, url.url()); 2088 return Window::retrieve(p); 2089 } 2090 if (browserArgs.frameName.toLower() == "replace") { 2091 Window::retrieveWindow(p)->goURL(exec, url.url(), true/*lock history*/); 2092 return Window::retrieve(p); 2093 } 2094 args.setMimeType("text/html"); 2095 args.setActionRequestedByUser(false); 2096 2097 // request window (new or existing if framename is set) 2098 KParts::ReadOnlyPart *newPart = nullptr; 2099 emit p->browserExtension()->createNewWindow(QUrl(), args, browserArgs, winargs, &newPart); 2100 if (newPart && qobject_cast<KHTMLPart *>(newPart)) { 2101 KHTMLPart *khtmlpart = static_cast<KHTMLPart *>(newPart); 2102 //qDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window); 2103 khtmlpart->setOpener(p); 2104 khtmlpart->setOpenedByJS(true); 2105 if (khtmlpart->document().isNull()) { 2106 khtmlpart->begin(); 2107 khtmlpart->write("<HTML><BODY>"); 2108 khtmlpart->end(); 2109 if (p->docImpl()) { 2110 //qCDebug(KHTML_LOG) << "Setting domain to " << p->docImpl()->domain().string(); 2111 khtmlpart->docImpl()->setOrigin(p->docImpl()->origin()); 2112 khtmlpart->docImpl()->setBaseURL(p->docImpl()->baseURL()); 2113 } 2114 } 2115 args.setMimeType(QString()); 2116 if (browserArgs.frameName.toLower() == "_blank") { 2117 browserArgs.frameName.clear(); 2118 } 2119 if (!url.isEmpty()) { 2120 emit khtmlpart->browserExtension()->openUrlRequest(url, args, browserArgs); 2121 } 2122 return Window::retrieve(khtmlpart); // global object 2123 } else { 2124 return jsUndefined(); 2125 } 2126 } 2127 2128 void Window::forgetSuppressedWindows() 2129 { 2130 m_suppressedWindowInfo.clear(); 2131 } 2132 2133 void Window::showSuppressedWindows() 2134 { 2135 KHTMLPart *part = qobject_cast<KHTMLPart *>(m_frame->m_part); 2136 KJS::Interpreter *interpreter = part->jScript()->interpreter(); 2137 ExecState *exec = interpreter->globalExec(); 2138 2139 QList<SuppressedWindowInfo> suppressedWindowInfo = m_suppressedWindowInfo; 2140 m_suppressedWindowInfo.clear(); 2141 foreach (const SuppressedWindowInfo &info, suppressedWindowInfo) { 2142 executeOpenWindow(exec, info.url, info.frameName, info.features); 2143 } 2144 } 2145 2146 class DelayedClose: public Window::DelayedAction 2147 { 2148 public: 2149 bool execute(Window *win) override 2150 { 2151 win->scheduleClose(); 2152 return false; 2153 } 2154 private: 2155 int steps; 2156 }; 2157 2158 JSValue *WindowFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 2159 { 2160 KJS_CHECK_THIS(Window, thisObj); 2161 2162 // these should work no matter whether the window is already 2163 // closed or not 2164 if (id == Window::ValueOf || id == Window::ToString) { 2165 return jsString("[object Window]"); 2166 } 2167 2168 Window *window = static_cast<Window *>(thisObj); 2169 QString str, str2; 2170 2171 KHTMLPart *part = qobject_cast<KHTMLPart *>(window->m_frame->m_part); 2172 if (!part) { 2173 return jsUndefined(); 2174 } 2175 2176 KHTMLView *widget = part->view(); 2177 JSValue *v = args[0]; 2178 UString s; 2179 s = v->toString(exec); 2180 str = s.qstring(); 2181 2182 QString caption; 2183 if (part && !part->url().host().isEmpty()) { 2184 caption = part->url().host() + " - "; 2185 } 2186 caption += "JavaScript"; // TODO: i18n 2187 // functions that work everywhere 2188 switch (id) { 2189 case Window::Alert: { 2190 TimerPauser pause(exec); 2191 if (!widget->dialogsAllowed()) { 2192 return jsUndefined(); 2193 } 2194 if (part && part->xmlDocImpl()) { 2195 part->xmlDocImpl()->updateRendering(); 2196 } 2197 if (part) { 2198 emit part->browserExtension()->requestFocus(part); 2199 } 2200 KMessageBox::error(widget, Qt::convertFromPlainText(str), caption); 2201 return jsUndefined(); 2202 } 2203 case Window::Confirm: { 2204 TimerPauser pause(exec); 2205 if (!widget->dialogsAllowed()) { 2206 return jsUndefined(); 2207 } 2208 if (part && part->xmlDocImpl()) { 2209 part->xmlDocImpl()->updateRendering(); 2210 } 2211 if (part) { 2212 emit part->browserExtension()->requestFocus(part); 2213 } 2214 return jsBoolean((KMessageBox::warningTwoActions(widget, Qt::convertFromPlainText(str), caption, 2215 KStandardGuiItem::ok(), KStandardGuiItem::cancel()) == KMessageBox::PrimaryAction)); 2216 } 2217 case Window::Prompt: { 2218 TimerPauser pause(exec); 2219 #ifndef KONQ_EMBEDDED 2220 if (!widget->dialogsAllowed()) { 2221 return jsUndefined(); 2222 } 2223 if (part && part->xmlDocImpl()) { 2224 part->xmlDocImpl()->updateRendering(); 2225 } 2226 if (part) { 2227 emit part->browserExtension()->requestFocus(part); 2228 } 2229 bool ok; 2230 if (args.size() >= 2) 2231 str2 = QInputDialog::getText(widget, caption, 2232 Qt::convertFromPlainText(str), QLineEdit::Normal, 2233 args[1]->toString(exec).qstring(), &ok); 2234 else 2235 str2 = QInputDialog::getText(widget, caption, 2236 Qt::convertFromPlainText(str), 2237 QLineEdit::Normal, QString(), &ok); 2238 if (ok) { 2239 return jsString(UString(str2)); 2240 } else { 2241 return jsNull(); 2242 } 2243 #else 2244 return jsUndefined(); 2245 #endif 2246 } 2247 case Window::GetComputedStyle: { 2248 if (!part || !part->xmlDocImpl()) { 2249 return jsUndefined(); 2250 } 2251 DOM::NodeImpl *arg0 = toNode(args[0]); 2252 if (!arg0 || arg0->nodeType() != DOM::Node::ELEMENT_NODE) { 2253 return jsUndefined(); // throw exception? 2254 } else 2255 return getDOMCSSStyleDeclaration(exec, part->xmlDocImpl()->defaultView()->getComputedStyle( 2256 static_cast<DOM::ElementImpl *>(arg0), args[1]->toString(exec).domString().implementation())); 2257 } 2258 case Window::Open: 2259 return window->openWindow(exec, args); 2260 case Window::Close: { 2261 /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm : 2262 The close method closes only windows opened by JavaScript using the open method. 2263 If you attempt to close any other window, a confirm is generated, which 2264 lets the user choose whether the window closes. 2265 This is a security feature to prevent "mail bombs" containing self.close(). 2266 However, if the window has only one document (the current one) in its 2267 session history, the close is allowed without any confirm. This is a 2268 special case for one-off windows that need to open other windows and 2269 then dispose of themselves. 2270 */ 2271 bool doClose = false; 2272 if (!part->openedByJS()) { 2273 // To conform to the SPEC, we only ask if the window 2274 // has more than one entry in the history (NS does that too). 2275 History history(exec, part); 2276 2277 if (history.get(exec, "length")->toInt32(exec) <= 1) { 2278 doClose = true; 2279 } else { 2280 // Can we get this dialog with tabs??? Does it close the window or the tab in that case? 2281 emit part->browserExtension()->requestFocus(part); 2282 if (KMessageBox::questionTwoActions(window->part()->widget(), 2283 i18n("Close window?"), i18n("Confirmation Required"), 2284 KStandardGuiItem::close(), KStandardGuiItem::cancel()) 2285 == KMessageBox::PrimaryAction) { 2286 doClose = true; 2287 } 2288 } 2289 } else { 2290 doClose = true; 2291 } 2292 2293 if (doClose) { 2294 // If this is the current window (the one the interpreter runs in), 2295 // then schedule a delayed close (so that the script terminates first). 2296 // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name"); 2297 if (Window::retrieveActive(exec) == window) { 2298 if (widget) { 2299 // quit all dialogs of this view 2300 // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash 2301 widget->closeChildDialogs(); 2302 } 2303 //qCDebug(KHTML_LOG) << "scheduling delayed close"; 2304 // We'll close the window at the end of the script execution 2305 Window *w = const_cast<Window *>(window); 2306 w->m_delayed.append(new DelayedClose); 2307 } else { 2308 //qCDebug(KHTML_LOG) << "closing NOW"; 2309 (const_cast<Window *>(window))->closeNow(); 2310 } 2311 } 2312 return jsUndefined(); 2313 } 2314 case Window::GetSelection: 2315 return new KJS::DOMSelection(exec, part->xmlDocImpl()); 2316 2317 case Window::Navigate: 2318 window->goURL(exec, args[0]->toString(exec).qstring()); 2319 return jsUndefined(); 2320 case Window::Focus: { 2321 KHTMLSettings::KJSWindowFocusPolicy policy = 2322 part->settings()->windowFocusPolicy(part->url().host()); 2323 if (policy == KHTMLSettings::KJSWindowFocusAllow && widget) { 2324 widget->topLevelWidget()->raise(); 2325 #if HAVE_X11 2326 KWindowSystem::unminimizeWindow(widget->topLevelWidget()->winId()); 2327 #else 2328 //TODO 2329 #endif 2330 widget->activateWindow(); 2331 emit part->browserExtension()->requestFocus(part); 2332 } 2333 return jsUndefined(); 2334 } 2335 case Window::Blur: 2336 // TODO 2337 return jsUndefined(); 2338 case Window::BToA: 2339 case Window::AToB: { 2340 if (!s.is8Bit()) { 2341 return jsUndefined(); 2342 } 2343 QByteArray in, out; 2344 char *binData = s.ascii(); 2345 in = QByteArray(binData, s.size()); 2346 if (id == Window::AToB) { 2347 out = QByteArray::fromBase64(in); 2348 } else { 2349 out = in.toBase64(); 2350 } 2351 UChar *d = new UChar[out.size()]; 2352 for (int i = 0; i < out.size(); i++) { 2353 d[i].uc = (uchar) out[i]; 2354 } 2355 UString ret(d, out.size(), false /*no copy*/); 2356 return jsString(ret); 2357 } 2358 case Window::PostMessage: { 2359 // Get our own origin. 2360 if (!part->xmlDocImpl()) { 2361 setDOMException(exec, DOM::DOMException::SECURITY_ERR); 2362 return jsUndefined(); 2363 } 2364 2365 QString sourceOrigin = part->xmlDocImpl()->origin()->toString(); 2366 QString targetOrigin = args[1]->toString(exec).qstring(); 2367 QUrl targetURL(targetOrigin); 2368 // qCDebug(KHTML_LOG) << "postMessage targetting:" << targetOrigin; 2369 2370 // Make sure we get * or an absolute URL for target origin 2371 if (targetOrigin != QLatin1String("*") && 2372 !(targetURL.isValid() && !targetURL.isRelative() && !targetURL.isEmpty())) { 2373 setDOMException(exec, DOM::DOMException::SYNTAX_ERR); 2374 return jsUndefined(); 2375 } 2376 2377 // Grab a snapshot of the data. Unfortunately it means we copy it 2378 // twice, but it's simpler than having separate code for swizzling 2379 // prototype pointers. 2380 JSValue *payload = cloneData(exec, args[0]); 2381 2382 // Queue the actual action, for after script execution. 2383 window->m_delayed.append(new DelayedPostMessage(part, sourceOrigin, targetOrigin, payload)); 2384 } 2385 2386 }; 2387 2388 // now unsafe functions.. 2389 if (!window->isSafeScript(exec)) { 2390 return jsUndefined(); 2391 } 2392 2393 switch (id) { 2394 case Window::ScrollBy: 2395 if (args.size() == 2 && widget) { 2396 widget->scrollBy(args[0]->toInt32(exec), args[1]->toInt32(exec)); 2397 } 2398 return jsUndefined(); 2399 case Window::Scroll: 2400 case Window::ScrollTo: 2401 if (args.size() == 2 && widget) { 2402 widget->setContentsPos(args[0]->toInt32(exec), args[1]->toInt32(exec)); 2403 } 2404 return jsUndefined(); 2405 case Window::MoveBy: { 2406 KHTMLSettings::KJSWindowMovePolicy policy = 2407 part->settings()->windowMovePolicy(part->url().host()); 2408 if (policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget) { 2409 KParts::BrowserExtension *ext = part->browserExtension(); 2410 if (ext) { 2411 QWidget *tl = widget->topLevelWidget(); 2412 QRect sg = QApplication::desktop()->screenGeometry(tl); 2413 2414 QPoint dest = tl->pos() + QPoint(args[0]->toInt32(exec), args[1]->toInt32(exec)); 2415 // Security check (the spec talks about UniversalBrowserWrite to disable this check...) 2416 if (dest.x() >= sg.x() && dest.y() >= sg.x() && 2417 dest.x() + tl->width() <= sg.width() + sg.x() && 2418 dest.y() + tl->height() <= sg.height() + sg.y()) { 2419 emit ext->moveTopLevelWidget(dest.x(), dest.y()); 2420 } 2421 } 2422 } 2423 return jsUndefined(); 2424 } 2425 case Window::MoveTo: { 2426 KHTMLSettings::KJSWindowMovePolicy policy = 2427 part->settings()->windowMovePolicy(part->url().host()); 2428 if (policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget) { 2429 KParts::BrowserExtension *ext = part->browserExtension(); 2430 if (ext) { 2431 QWidget *tl = widget->topLevelWidget(); 2432 QRect sg = QApplication::desktop()->screenGeometry(tl); 2433 2434 QPoint dest(args[0]->toInt32(exec) + sg.x(), args[1]->toInt32(exec) + sg.y()); 2435 // Security check (the spec talks about UniversalBrowserWrite to disable this check...) 2436 if (dest.x() >= sg.x() && dest.y() >= sg.y() && 2437 dest.x() + tl->width() <= sg.width() + sg.x() && 2438 dest.y() + tl->height() <= sg.height() + sg.y()) { 2439 emit ext->moveTopLevelWidget(dest.x(), dest.y()); 2440 } 2441 } 2442 } 2443 return jsUndefined(); 2444 } 2445 case Window::ResizeBy: { 2446 KHTMLSettings::KJSWindowResizePolicy policy = 2447 part->settings()->windowResizePolicy(part->url().host()); 2448 if (policy == KHTMLSettings::KJSWindowResizeAllow 2449 && args.size() == 2 && widget) { 2450 QWidget *tl = widget->topLevelWidget(); 2451 QRect geom = tl->frameGeometry(); 2452 window->resizeTo(tl, 2453 geom.width() + args[0]->toInt32(exec), 2454 geom.height() + args[1]->toInt32(exec)); 2455 } 2456 return jsUndefined(); 2457 } 2458 case Window::ResizeTo: { 2459 KHTMLSettings::KJSWindowResizePolicy policy = 2460 part->settings()->windowResizePolicy(part->url().host()); 2461 if (policy == KHTMLSettings::KJSWindowResizeAllow 2462 && args.size() == 2 && widget) { 2463 QWidget *tl = widget->topLevelWidget(); 2464 window->resizeTo(tl, args[0]->toInt32(exec), args[1]->toInt32(exec)); 2465 } 2466 return jsUndefined(); 2467 } 2468 case Window::SetTimeout: 2469 case Window::SetInterval: { 2470 bool singleShot; 2471 int i; // timeout interval 2472 if (args.size() == 0) { 2473 return jsUndefined(); 2474 } 2475 if (args.size() > 1) { 2476 singleShot = (id == Window::SetTimeout); 2477 i = args[1]->toInt32(exec); 2478 } else { 2479 // second parameter is missing. Emulate Mozilla behavior. 2480 singleShot = true; 2481 i = 4; 2482 } 2483 if (v->type() == StringType) { 2484 int r = (const_cast<Window *>(window))->winq->installTimeout(Identifier(s), i, singleShot); 2485 return jsNumber(r); 2486 } else if (v->type() == ObjectType && v->getObject()->implementsCall()) { 2487 JSObject *func = v->getObject(); 2488 List funcArgs; 2489 ListIterator it = args.begin(); 2490 int argno = 0; 2491 while (it != args.end()) { 2492 JSValue *arg = it++; 2493 if (argno++ >= 2) { 2494 funcArgs.append(arg); 2495 } 2496 } 2497 if (args.size() < 2) { 2498 funcArgs.append(jsNumber(i)); 2499 } 2500 int r = (const_cast<Window *>(window))->winq->installTimeout(func, funcArgs, i, singleShot); 2501 return jsNumber(r); 2502 } else { 2503 return jsUndefined(); 2504 } 2505 } 2506 case Window::ClearTimeout: 2507 case Window::ClearInterval: 2508 (const_cast<Window *>(window))->winq->clearTimeout(v->toInt32(exec)); 2509 return jsUndefined(); 2510 case Window::Print: 2511 if (widget) { 2512 // ### TODO emit onbeforeprint event 2513 widget->print(); 2514 // ### TODO emit onafterprint event 2515 } 2516 case Window::CaptureEvents: 2517 case Window::ReleaseEvents: 2518 // Do nothing for now. These are NS-specific legacy calls. 2519 break; 2520 case Window::AddEventListener: { 2521 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); 2522 if (listener) { 2523 DOM::DocumentImpl *docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle()); 2524 if (docimpl) { 2525 docimpl->addWindowEventListener(EventName::fromString(args[0]->toString(exec).domString()), listener, args[2]->toBoolean(exec)); 2526 } else { 2527 qCWarning(KHTML_LOG) << "document missing on Window::AddEventListener. why?"; 2528 } 2529 } 2530 return jsUndefined(); 2531 } 2532 case Window::RemoveEventListener: { 2533 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); 2534 if (listener) { 2535 DOM::DocumentImpl *docimpl = static_cast<DOM::DocumentImpl *>(part->document().handle()); 2536 if (docimpl) { 2537 docimpl->removeWindowEventListener(EventName::fromString(args[0]->toString(exec).domString()), listener, args[2]->toBoolean(exec)); 2538 } else { 2539 qCWarning(KHTML_LOG) << "document missing on Window::RemoveEventListener. why?"; 2540 } 2541 } 2542 return jsUndefined(); 2543 } 2544 2545 } 2546 return jsUndefined(); 2547 } 2548 2549 ////////////////////// ScheduledAction //////////////////////// 2550 2551 ScheduledAction::ScheduledAction(JSObject *_func, const List &_args, const DateTimeMS &_nextTime, int _interval, bool _singleShot, 2552 int _timerId) 2553 { 2554 //qCDebug(KHTML_LOG) << "ScheduledAction::ScheduledAction(isFunction) " << this; 2555 func = static_cast<JSObject *>(_func); 2556 args = _args; 2557 isFunction = true; 2558 singleShot = _singleShot; 2559 nextTime = _nextTime; 2560 interval = _interval; 2561 executing = false; 2562 timerId = _timerId; 2563 } 2564 2565 ScheduledAction::ScheduledAction(const QString &_code, const DateTimeMS &_nextTime, int _interval, bool _singleShot, int _timerId) 2566 { 2567 //qCDebug(KHTML_LOG) << "ScheduledAction::ScheduledAction(!isFunction) " << this; 2568 //func = 0; 2569 //args = 0; 2570 func = nullptr; 2571 code = _code; 2572 isFunction = false; 2573 singleShot = _singleShot; 2574 nextTime = _nextTime; 2575 interval = _interval; 2576 executing = false; 2577 timerId = _timerId; 2578 } 2579 2580 bool ScheduledAction::execute(Window *window) 2581 { 2582 KHTMLPart *part = qobject_cast<KHTMLPart *>(window->m_frame->m_part); 2583 if (!part || !part->jScriptEnabled()) { 2584 return false; 2585 } 2586 ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(part->jScript()->interpreter()); 2587 2588 interpreter->setProcessingTimerCallback(true); 2589 2590 //qCDebug(KHTML_LOG) << "ScheduledAction::execute " << this; 2591 if (isFunction) { 2592 if (func->implementsCall()) { 2593 // #### check this 2594 Q_ASSERT(part); 2595 if (part) { 2596 KJS::Interpreter *interpreter = part->jScript()->interpreter(); 2597 ExecState *exec = interpreter->globalExec(); 2598 Q_ASSERT(window == interpreter->globalObject()); 2599 JSObject *obj(window); 2600 func->call(exec, obj, args); // note that call() creates its own execution state for the func call 2601 if (exec->hadException()) { 2602 exec->clearException(); 2603 } 2604 2605 // Update our document's rendering following the execution of the timeout callback. 2606 part->document().updateRendering(); 2607 } 2608 } 2609 } else { 2610 part->executeScript(DOM::Node(), code); 2611 } 2612 2613 interpreter->setProcessingTimerCallback(false); 2614 return true; 2615 } 2616 2617 void ScheduledAction::mark() 2618 { 2619 if (func && !func->marked()) { 2620 func->mark(); 2621 } 2622 } 2623 2624 ScheduledAction::~ScheduledAction() 2625 { 2626 args.reset(); 2627 //qCDebug(KHTML_LOG) << "ScheduledAction::~ScheduledAction " << this; 2628 } 2629 2630 ////////////////////// WindowQObject //////////////////////// 2631 2632 WindowQObject::WindowQObject(Window *w) 2633 : parent(w) 2634 { 2635 //qCDebug(KHTML_LOG) << "WindowQObject::WindowQObject " << this; 2636 if (!parent->m_frame) { 2637 // qCDebug(KHTML_LOG) << "WARNING: null part in " ; 2638 } else 2639 connect(parent->m_frame, SIGNAL(destroyed()), 2640 this, SLOT(parentDestroyed())); 2641 pauseLevel = 0; 2642 lastTimerId = 0; 2643 currentlyDispatching = false; 2644 } 2645 2646 WindowQObject::~WindowQObject() 2647 { 2648 //qCDebug(KHTML_LOG) << "WindowQObject::~WindowQObject " << this; 2649 parentDestroyed(); // reuse same code 2650 } 2651 2652 void WindowQObject::parentDestroyed() 2653 { 2654 killTimers(); 2655 2656 while (!scheduledActions.isEmpty()) { 2657 delete scheduledActions.takeFirst(); 2658 } 2659 scheduledActions.clear(); 2660 } 2661 2662 void WindowQObject::pauseTimers() 2663 { 2664 ++pauseLevel; 2665 if (pauseLevel == 1) { 2666 pauseStart = DateTimeMS::now(); 2667 } 2668 } 2669 2670 void WindowQObject::resumeTimers() 2671 { 2672 if (pauseLevel == 1) { 2673 // Adjust all timers by the delay length, making sure there is a minimum 2674 // margin from current time, however, so we don't go stampeding off if 2675 // there is some unwanted recursion, etc. 2676 DateTimeMS curTime = DateTimeMS::now(); 2677 DateTimeMS earliestDispatch = curTime.addMSecs(5); 2678 int delay = pauseStart.msecsTo(curTime); 2679 foreach (ScheduledAction *action, scheduledActions) { 2680 action->nextTime = action->nextTime.addMSecs(delay); 2681 if (earliestDispatch > action->nextTime) { 2682 action->nextTime = earliestDispatch; 2683 } 2684 } 2685 2686 // Dispatch any timers that may have been ignored if ::timerEvent fell in the middle 2687 // of a pause.. 2688 timerEvent(nullptr); 2689 } 2690 2691 --pauseLevel; // We do it afterwards so that timerEvent can know about us. 2692 } 2693 2694 int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot) 2695 { 2696 int id = ++lastTimerId; 2697 if (t < 10) { 2698 t = 10; 2699 } 2700 DateTimeMS nextTime = DateTimeMS::now().addMSecs(t); 2701 2702 ScheduledAction *action = new ScheduledAction(handler.qstring(), nextTime, t, singleShot, id); 2703 scheduledActions.append(action); 2704 setNextTimer(); 2705 return id; 2706 } 2707 2708 int WindowQObject::installTimeout(JSValue *func, List args, int t, bool singleShot) 2709 { 2710 JSObject *objFunc = func->getObject(); 2711 if (!objFunc) { 2712 return 0; 2713 } 2714 int id = ++lastTimerId; 2715 if (t < 10) { 2716 t = 10; 2717 } 2718 2719 DateTimeMS nextTime = DateTimeMS::now().addMSecs(t); 2720 ScheduledAction *action = new ScheduledAction(objFunc, args, nextTime, t, singleShot, id); 2721 scheduledActions.append(action); 2722 setNextTimer(); 2723 return id; 2724 } 2725 2726 void WindowQObject::clearTimeout(int timerId) 2727 { 2728 foreach (ScheduledAction *action, scheduledActions) { 2729 if (action->timerId == timerId) { 2730 scheduledActions.removeAll(action); 2731 if (!action->executing) { 2732 delete action; 2733 } 2734 return; 2735 } 2736 } 2737 } 2738 2739 bool WindowQObject::hasTimers() const 2740 { 2741 return scheduledActions.count(); 2742 } 2743 2744 void WindowQObject::mark() 2745 { 2746 foreach (ScheduledAction *action, scheduledActions) { 2747 action->mark(); 2748 } 2749 } 2750 2751 void WindowQObject::timerEvent(QTimerEvent *) 2752 { 2753 killTimers(); 2754 2755 if (scheduledActions.isEmpty()) { 2756 return; 2757 } 2758 2759 if (pauseLevel) { 2760 return; 2761 } 2762 2763 currentlyDispatching = true; 2764 2765 DateTimeMS current = DateTimeMS::now(); 2766 2767 // Work out which actions are to be executed. We take a separate copy of 2768 // this list since the main one may be modified during action execution 2769 QList<ScheduledAction *> toExecute; 2770 foreach (ScheduledAction *action, scheduledActions) { 2771 if (current >= action->nextTime) { 2772 toExecute.append(action); 2773 } 2774 } 2775 2776 // ### verify that the window can't be closed (and action deleted) during execution 2777 foreach (ScheduledAction *action, toExecute) { 2778 if (!scheduledActions.count(action)) { // removed by clearTimeout() 2779 continue; 2780 } 2781 2782 action->executing = true; // prevent deletion in clearTimeout() 2783 2784 if (parent->part()) { 2785 bool ok = action->execute(parent); 2786 if (!ok) { // e.g. JS disabled 2787 scheduledActions.removeAll(action); 2788 } 2789 } 2790 2791 if (action->singleShot) { 2792 scheduledActions.removeAll(action); 2793 } 2794 2795 action->executing = false; 2796 2797 if (!scheduledActions.count(action)) { 2798 delete action; 2799 } else { 2800 action->nextTime = action->nextTime.addMSecs(action->interval); 2801 } 2802 } 2803 2804 currentlyDispatching = false; 2805 2806 // Work out when next event is to occur 2807 setNextTimer(); 2808 2809 // unless we're inside a nested context, do post-script processing 2810 if (!pauseLevel) { 2811 parent->afterScriptExecution(); 2812 } 2813 } 2814 2815 DateTimeMS DateTimeMS::addMSecs(int s) const 2816 { 2817 DateTimeMS c = *this; 2818 c.mTime = mTime.addMSecs(s); 2819 if (s > 0) { 2820 if (c.mTime < mTime) { 2821 c.mDate = mDate.addDays(1); 2822 } 2823 } else { 2824 if (c.mTime > mTime) { 2825 c.mDate = mDate.addDays(-1); 2826 } 2827 } 2828 return c; 2829 } 2830 2831 bool DateTimeMS::operator >(const DateTimeMS &other) const 2832 { 2833 if (mDate > other.mDate) { 2834 return true; 2835 } 2836 2837 if (mDate < other.mDate) { 2838 return false; 2839 } 2840 2841 return mTime > other.mTime; 2842 } 2843 2844 bool DateTimeMS::operator >=(const DateTimeMS &other) const 2845 { 2846 if (mDate > other.mDate) { 2847 return true; 2848 } 2849 2850 if (mDate < other.mDate) { 2851 return false; 2852 } 2853 2854 return mTime >= other.mTime; 2855 } 2856 2857 int DateTimeMS::msecsTo(const DateTimeMS &other) const 2858 { 2859 int d = mDate.daysTo(other.mDate); 2860 int ms = mTime.msecsTo(other.mTime); 2861 return d * 24 * 60 * 60 * 1000 + ms; 2862 } 2863 2864 DateTimeMS DateTimeMS::now() 2865 { 2866 DateTimeMS t; 2867 QTime before = QTime::currentTime(); 2868 t.mDate = QDate::currentDate(); 2869 t.mTime = QTime::currentTime(); 2870 if (t.mTime < before) { 2871 t.mDate = QDate::currentDate(); // prevent race condition in hacky way :) 2872 } 2873 return t; 2874 } 2875 2876 void WindowQObject::setNextTimer() 2877 { 2878 if (currentlyDispatching) { 2879 return; // Will schedule at the end 2880 } 2881 2882 if (scheduledActions.isEmpty()) { 2883 return; 2884 } 2885 2886 QListIterator<ScheduledAction *> it(scheduledActions); 2887 DateTimeMS nextTime = it.next()->nextTime; 2888 while (it.hasNext()) { 2889 const DateTimeMS &currTime = it.next()->nextTime; 2890 if (nextTime > currTime) { 2891 nextTime = currTime; 2892 } 2893 } 2894 2895 int nextInterval = DateTimeMS::now().msecsTo(nextTime); 2896 if (nextInterval < 0) { 2897 nextInterval = 0; 2898 } 2899 timerIds.append(startTimer(nextInterval)); 2900 } 2901 2902 void WindowQObject::killTimers() 2903 { 2904 for (int i = 0; i < timerIds.size(); ++i) { 2905 killTimer(timerIds.at(i)); 2906 } 2907 timerIds.clear(); 2908 } 2909 2910 void WindowQObject::timeoutClose() 2911 { 2912 parent->closeNow(); 2913 } 2914 2915 ////////////////////// Location Object //////////////////////// 2916 2917 const ClassInfo Location::info = { "Location", nullptr, &LocationTable, nullptr }; 2918 /* 2919 @begin LocationTable 11 2920 hash Location::Hash DontDelete 2921 host Location::Host DontDelete 2922 hostname Location::Hostname DontDelete 2923 href Location::Href DontDelete 2924 pathname Location::Pathname DontDelete 2925 port Location::Port DontDelete 2926 protocol Location::Protocol DontDelete 2927 search Location::Search DontDelete 2928 [[==]] Location::EqualEqual DontDelete|ReadOnly 2929 assign Location::Assign DontDelete|Function 1 2930 toString Location::ToString DontDelete|Function 0 2931 replace Location::Replace DontDelete|Function 1 2932 reload Location::Reload DontDelete|Function 0 2933 @end 2934 */ 2935 KJS_IMPLEMENT_PROTOFUNC(LocationFunc) 2936 Location::Location(khtml::ChildFrame *f) : m_frame(f) 2937 { 2938 //qCDebug(KHTML_LOG) << "Location::Location " << this << " m_part=" << (void*)m_part; 2939 } 2940 2941 Location::~Location() 2942 { 2943 //qCDebug(KHTML_LOG) << "Location::~Location " << this << " m_part=" << (void*)m_part; 2944 } 2945 2946 KParts::ReadOnlyPart *Location::part() const 2947 { 2948 return m_frame ? static_cast<KParts::ReadOnlyPart *>(m_frame->m_part) : nullptr; 2949 } 2950 2951 bool Location::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot &slot) 2952 { 2953 #ifdef KJS_VERBOSE 2954 qCDebug(KHTML_LOG) << "Location::getOwnPropertySlot " << p.qstring() << " m_part=" << (void *)m_frame->m_part; 2955 #endif 2956 2957 if (m_frame.isNull() || m_frame->m_part.isNull()) { 2958 return jsUndefined(); 2959 } 2960 2961 const HashEntry *entry = Lookup::findEntry(&LocationTable, p); 2962 2963 if (entry) { 2964 // properties that work on all Location objects 2965 if (entry->value == Replace) { 2966 getSlotFromEntry<LocationFunc, Location>(entry, this, slot); 2967 return true; 2968 } 2969 2970 // XSS check 2971 const Window *window = Window::retrieveWindow(m_frame->m_part); 2972 if (!window || !window->isSafeScript(exec)) { 2973 slot.setUndefined(this); 2974 return true; 2975 } 2976 2977 // XSS check passed - can now dispatch normally. 2978 getSlotFromEntry<LocationFunc, Location>(entry, this, slot); 2979 return true; 2980 } 2981 2982 return JSObject::getOwnPropertySlot(exec, p, slot); 2983 } 2984 2985 JSValue *Location::getValueProperty(ExecState *exec, int token) const 2986 { 2987 QUrl url = m_frame->m_part->url(); 2988 switch (token) { 2989 case Hash: { 2990 const QString encodedHash = url.fragment(QUrl::FullyEncoded); 2991 if (encodedHash.isEmpty()) { 2992 return jsString(""); 2993 } 2994 return jsString(QLatin1Char('#') + encodedHash); 2995 } 2996 case Host: { 2997 UString str = url.host(); 2998 if (url.port() > 0) { 2999 str += QString(QLatin1Char(':') + QString::number(url.port())); 3000 } 3001 return jsString(str); 3002 // Note: this is the IE spec. The NS spec swaps the two, it says 3003 // "The hostname property is the concatenation of the host and port properties, separated by a colon." 3004 // Bleh. 3005 } 3006 case Hostname: 3007 return jsString(UString(url.host())); 3008 case Href: 3009 if (url.isEmpty()) { 3010 return jsString("about:blank"); 3011 } else if (url.path().isEmpty()) { 3012 return jsString(UString(url.toDisplayString() + '/')); 3013 } else { 3014 return jsString(UString(url.toDisplayString())); 3015 } 3016 case Pathname: 3017 if (url.isEmpty()) { 3018 return jsString(""); 3019 } 3020 return jsString(UString(url.path().isEmpty() ? QString("/") : url.path())); 3021 case Port: 3022 return jsString(UString(url.port() > 0 ? QString::number(url.port()) : QLatin1String(""))); 3023 case Protocol: 3024 return jsString(UString(url.scheme() + ':')); 3025 case Search: 3026 return jsString(UString(url.query())); 3027 case EqualEqual: // [[==]] 3028 return jsString(toString(exec)); 3029 } 3030 return jsUndefined(); 3031 } 3032 3033 void Location::put(ExecState *exec, const Identifier &p, JSValue *v, int attr) 3034 { 3035 #ifdef KJS_VERBOSE 3036 qCDebug(KHTML_LOG) << "Location::put " << p.qstring() << " m_part=" << (void *)m_frame->m_part; 3037 #endif 3038 if (m_frame.isNull() || m_frame->m_part.isNull()) { 3039 return; 3040 } 3041 3042 Window *window = Window::retrieveWindow(m_frame->m_part); 3043 if (!window) { 3044 return; 3045 } 3046 3047 QUrl url = m_frame->m_part->url(); 3048 3049 const HashEntry *entry = Lookup::findEntry(&LocationTable, p); 3050 3051 if (entry) { 3052 3053 // XSS check. Only new hrefs can be set from other sites 3054 if (entry->value != Href && !window->isSafeScript(exec)) { 3055 return; 3056 } 3057 3058 QString str = v->toString(exec).qstring(); 3059 switch (entry->value) { 3060 case Href: { 3061 KHTMLPart *p = qobject_cast<KHTMLPart *>(Window::retrieveActive(exec)->part()); 3062 if (p) { 3063 url = QUrl(p->htmlDocument().completeURL(str).string()); 3064 } else { 3065 url = QUrl(str); 3066 } 3067 break; 3068 } 3069 case Hash: 3070 // Strip any leading # --- setting hash to #foo is the same as setting it to foo. 3071 if (str.startsWith(QLatin1Char('#'))) { 3072 str = str.mid(1); 3073 } 3074 3075 // Note that we want to do gotoAnchor even when the hash is already set, so we 3076 // scroll the destination into view. 3077 3078 // Setting this must always provide a ref, even if just # see 3079 // HTML5 2.6. 3080 if (str.isEmpty()) { 3081 url.setFragment(""); 3082 } else { 3083 url.setFragment(QUrl::fromPercentEncoding(str.toUtf8()), QUrl::DecodedMode); 3084 } 3085 break; 3086 case Host: { 3087 QString host = str.left(str.indexOf(":")); 3088 QString port = str.mid(str.indexOf(":") + 1); 3089 url.setHost(host); 3090 url.setPort(port.toUInt()); 3091 break; 3092 } 3093 case Hostname: 3094 url.setHost(str); 3095 break; 3096 case Pathname: 3097 url.setPath(str); 3098 break; 3099 case Port: 3100 url.setPort(str.toUInt()); 3101 break; 3102 case Protocol: 3103 url.setScheme(str); 3104 break; 3105 case Search: 3106 url.setQuery(str); 3107 break; 3108 } 3109 } else { 3110 JSObject::put(exec, p, v, attr); 3111 return; 3112 } 3113 3114 window->goURL(exec, url.url()); 3115 } 3116 3117 JSValue *Location::toPrimitive(ExecState *exec, JSType) const 3118 { 3119 if (m_frame) { 3120 Window *window = Window::retrieveWindow(m_frame->m_part); 3121 if (window && window->isSafeScript(exec)) { 3122 return jsString(toString(exec)); 3123 } 3124 } 3125 return jsUndefined(); 3126 } 3127 3128 UString Location::toString(ExecState *exec) const 3129 { 3130 if (m_frame) { 3131 Window *window = Window::retrieveWindow(m_frame->m_part); 3132 if (window && window->isSafeScript(exec)) { 3133 QUrl url = m_frame->m_part->url(); 3134 if (url.isEmpty()) { 3135 return "about:blank"; 3136 } else if (url.path().isEmpty()) { 3137 return QString(url.toDisplayString() + '/'); 3138 } else { 3139 return url.toDisplayString(); 3140 } 3141 } 3142 } 3143 return ""; 3144 } 3145 3146 JSValue *LocationFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 3147 { 3148 KJS_CHECK_THIS(Location, thisObj); 3149 Location *location = static_cast<Location *>(thisObj); 3150 KParts::ReadOnlyPart *part = location->part(); 3151 3152 if (!part) { 3153 return jsUndefined(); 3154 } 3155 3156 Window *window = Window::retrieveWindow(part); 3157 3158 if (!window->isSafeScript(exec) && id != Location::Replace) { 3159 return jsUndefined(); 3160 } 3161 3162 switch (id) { 3163 case Location::Assign: 3164 window->goURL(exec, args[0]->toString(exec).qstring()); 3165 break; 3166 case Location::Replace: 3167 window->goURL(exec, args[0]->toString(exec).qstring(), true/*lock history*/); 3168 break; 3169 case Location::Reload: { 3170 KHTMLPart *khtmlpart = qobject_cast<KHTMLPart *>(part); 3171 if (khtmlpart) { 3172 khtmlpart->scheduleRedirection(-1, part->url().toString(), true/*lock history*/); 3173 } else { 3174 part->openUrl(part->url()); 3175 } 3176 break; 3177 } 3178 case Location::ToString: 3179 return jsString(location->toString(exec)); 3180 } 3181 return jsUndefined(); 3182 } 3183 3184 ////////////////////// External Object //////////////////////// 3185 3186 const ClassInfo External::info = { "External", nullptr, nullptr, nullptr }; 3187 /* 3188 @begin ExternalTable 4 3189 addFavorite External::AddFavorite DontDelete|Function 1 3190 @end 3191 */ 3192 KJS_IMPLEMENT_PROTOFUNC(ExternalFunc) 3193 3194 bool External::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot &propertySlot) 3195 { 3196 return getStaticFunctionSlot<ExternalFunc, JSObject>(exec, &ExternalTable, this, p, propertySlot); 3197 } 3198 3199 JSValue *ExternalFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 3200 { 3201 KJS_CHECK_THIS(External, thisObj); 3202 External *external = static_cast<External *>(thisObj); 3203 3204 KHTMLPart *part = external->part; 3205 if (!part) { 3206 return jsUndefined(); 3207 } 3208 3209 switch (id) { 3210 case External::AddFavorite: { 3211 #ifndef KONQ_EMBEDDED 3212 KHTMLView *widget = part->view(); 3213 if (!widget->dialogsAllowed()) { 3214 return jsUndefined(); 3215 } 3216 part->xmlDocImpl()->updateRendering(); 3217 if (args.size() != 1 && args.size() != 2) { 3218 return jsUndefined(); 3219 } 3220 3221 QString url = args[0]->toString(exec).qstring(); 3222 QString title; 3223 if (args.size() == 2) { 3224 title = args[1]->toString(exec).qstring(); 3225 } 3226 3227 // AK - don't do anything yet, for the moment i 3228 // just wanted the base js handling code in cvs 3229 return jsUndefined(); 3230 3231 QString question; 3232 if (title.isEmpty()) 3233 question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?", 3234 url); 3235 else 3236 question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?", 3237 url, title); 3238 3239 emit part->browserExtension()->requestFocus(part); 3240 3241 QString caption; 3242 if (!part->url().host().isEmpty()) { 3243 caption = part->url().host() + " - "; 3244 } 3245 caption += i18n("JavaScript Attempted Bookmark Insert"); 3246 3247 if (KMessageBox::warningTwoActions( 3248 widget, question, caption, 3249 KGuiItem(i18n("Insert")), KGuiItem(i18n("Disallow"))) == KMessageBox::PrimaryAction) { 3250 KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager(); 3251 KBookmarkDialog dlg(mgr, nullptr); 3252 dlg.addBookmark(title, QUrl(url), KIO::iconNameForUrl(QUrl(url))); 3253 } 3254 #else 3255 return jsUndefined(); 3256 #endif 3257 break; 3258 } 3259 default: 3260 return jsUndefined(); 3261 } 3262 3263 return jsUndefined(); 3264 } 3265 3266 ////////////////////// History Object //////////////////////// 3267 3268 const ClassInfo History::info = { "History", nullptr, nullptr, nullptr }; 3269 /* 3270 @begin HistoryTable 4 3271 length History::Length DontDelete|ReadOnly 3272 back History::Back DontDelete|Function 0 3273 forward History::Forward DontDelete|Function 0 3274 go History::Go DontDelete|Function 1 3275 @end 3276 */ 3277 KJS_IMPLEMENT_PROTOFUNC(HistoryFunc) 3278 3279 bool History::getOwnPropertySlot(ExecState *exec, const Identifier &p, PropertySlot &slot) 3280 { 3281 return getStaticPropertySlot<HistoryFunc, History, JSObject>(exec, &HistoryTable, this, p, slot); 3282 } 3283 3284 JSValue *History::getValueProperty(ExecState *, int token) const 3285 { 3286 // if previous or next is implemented, make sure it is not a major 3287 // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/) 3288 switch (token) { 3289 case Length: { 3290 if (!part) { 3291 return jsNumber(0); 3292 } 3293 3294 KParts::BrowserExtension *ext = part->browserExtension(); 3295 if (!ext) { 3296 return jsNumber(0); 3297 } 3298 3299 KParts::BrowserInterface *iface = ext->browserInterface(); 3300 if (!iface) { 3301 return jsNumber(0); 3302 } 3303 3304 QVariant length = iface->property("historyLength"); 3305 3306 if (length.type() != QVariant::UInt) { 3307 return jsNumber(0); 3308 } 3309 3310 return jsNumber(length.toUInt()); 3311 } 3312 default: 3313 // qCDebug(KHTML_LOG) << "WARNING: Unhandled token in History::getValueProperty : " << token; 3314 return jsUndefined(); 3315 } 3316 } 3317 3318 JSValue *HistoryFunc::callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) 3319 { 3320 KJS_CHECK_THIS(History, thisObj); 3321 History *history = static_cast<History *>(thisObj); 3322 3323 JSValue *v = args[0]; 3324 double n = 0.0; 3325 if (v) { 3326 n = v->toInteger(exec); 3327 } 3328 3329 int steps; 3330 switch (id) { 3331 case History::Back: 3332 steps = -1; 3333 break; 3334 case History::Forward: 3335 steps = 1; 3336 break; 3337 case History::Go: 3338 steps = (int)n; 3339 break; 3340 default: 3341 return jsUndefined(); 3342 } 3343 3344 // Special case for go(0) from a frame -> reload only the frame 3345 // go(i!=0) from a frame navigates into the history of the frame only, 3346 // in both IE and NS (but not in Mozilla).... we can't easily do that 3347 // in Konqueror... 3348 if (!steps) { // add && history->part->parentPart() to get only frames, but doesn't matter 3349 history->part->openUrl(history->part->url()); /// ## need args.reload=true? 3350 } else { 3351 // Delay it. 3352 // Testcase: history.back(); alert("hello"); 3353 Window *window = Window::retrieveWindow(history->part); 3354 window->delayedGoHistory(steps); 3355 } 3356 return jsUndefined(); 3357 } 3358 3359 } // namespace KJS 3360 3361 #include "moc_kjs_window.cpp"