khtml Library API Documentation

kjs_window.cpp

00001 // -*- c-basic-offset: 2 -*- 00002 /* 00003 * This file is part of the KDE libraries 00004 * Copyright (C) 2000-2003 Harri Porten (porten@kde.org) 00005 * Copyright (C) 2001-2003 David Faure (faure@kde.org) 00006 * Copyright (C) 2003 Apple Computer, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Library General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Library General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Library General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00021 */ 00022 #include "config.h" 00023 00024 #include <qstylesheet.h> 00025 #include <qtimer.h> 00026 #include <qpaintdevicemetrics.h> 00027 #include <qapplication.h> 00028 #include <kdebug.h> 00029 #include <kmessagebox.h> 00030 #include <kinputdialog.h> 00031 #include <klocale.h> 00032 #include <kparts/browserinterface.h> 00033 #include <kwin.h> 00034 00035 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00036 #include <kwinmodule.h> // schroder 00037 #endif 00038 00039 #include <kbookmarkmanager.h> 00040 #include <kglobalsettings.h> 00041 #include <assert.h> 00042 #include <qstyle.h> 00043 #include <qobjectlist.h> 00044 #include <kstringhandler.h> 00045 00046 #include "kjs_proxy.h" 00047 #include "kjs_window.h" 00048 #include "kjs_navigator.h" 00049 #include "kjs_mozilla.h" 00050 #include "kjs_html.h" 00051 #include "kjs_range.h" 00052 #include "kjs_traversal.h" 00053 #include "kjs_css.h" 00054 #include "kjs_events.h" 00055 #include "xmlhttprequest.h" 00056 00057 #include "khtmlview.h" 00058 #include "khtml_part.h" 00059 #include "khtml_settings.h" 00060 #include "xml/dom2_eventsimpl.h" 00061 #include "xml/dom_docimpl.h" 00062 #include "misc/htmltags.h" 00063 #include "html/html_documentimpl.h" 00064 00065 using namespace KJS; 00066 00067 namespace KJS { 00068 00069 class History : public ObjectImp { 00070 friend class HistoryFunc; 00071 public: 00072 History(ExecState *exec, KHTMLPart *p) 00073 : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { } 00074 virtual Value get(ExecState *exec, const Identifier &propertyName) const; 00075 Value getValueProperty(ExecState *exec, int token) const; 00076 virtual const ClassInfo* classInfo() const { return &info; } 00077 static const ClassInfo info; 00078 enum { Back, Forward, Go, Length }; 00079 private: 00080 QGuardedPtr<KHTMLPart> part; 00081 }; 00082 00083 class External : public ObjectImp { 00084 friend class ExternalFunc; 00085 public: 00086 External(ExecState *exec, KHTMLPart *p) 00087 : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { } 00088 virtual Value get(ExecState *exec, const Identifier &propertyName) const; 00089 virtual const ClassInfo* classInfo() const { return &info; } 00090 static const ClassInfo info; 00091 enum { AddFavorite }; 00092 private: 00093 QGuardedPtr<KHTMLPart> part; 00094 }; 00095 00096 class FrameArray : public ObjectImp { 00097 public: 00098 FrameArray(ExecState *exec, KHTMLPart *p) 00099 : ObjectImp(exec->interpreter()->builtinObjectPrototype()), part(p) { } 00100 virtual Value get(ExecState *exec, const Identifier &propertyName) const; 00101 private: 00102 QGuardedPtr<KHTMLPart> part; 00103 }; 00104 00105 #ifdef Q_WS_QWS 00106 class KonquerorFunc : public DOMFunction { 00107 public: 00108 KonquerorFunc(const Konqueror* k, const char* name) 00109 : DOMFunction(), konqueror(k), m_name(name) { } 00110 virtual Value tryCall(ExecState *exec, Object &thisObj, const List &args); 00111 00112 private: 00113 const Konqueror* konqueror; 00114 QCString m_name; 00115 }; 00116 #endif 00117 } // namespace KJS 00118 00119 #include "kjs_window.lut.h" 00120 #include "rendering/render_replaced.h" 00121 00123 00124 // table for screen object 00125 /* 00126 @begin ScreenTable 7 00127 height Screen::Height DontEnum|ReadOnly 00128 width Screen::Width DontEnum|ReadOnly 00129 colorDepth Screen::ColorDepth DontEnum|ReadOnly 00130 pixelDepth Screen::PixelDepth DontEnum|ReadOnly 00131 availLeft Screen::AvailLeft DontEnum|ReadOnly 00132 availTop Screen::AvailTop DontEnum|ReadOnly 00133 availHeight Screen::AvailHeight DontEnum|ReadOnly 00134 availWidth Screen::AvailWidth DontEnum|ReadOnly 00135 @end 00136 */ 00137 00138 const ClassInfo Screen::info = { "Screen", 0, &ScreenTable, 0 }; 00139 00140 // We set the object prototype so that toString is implemented 00141 Screen::Screen(ExecState *exec) 00142 : ObjectImp(exec->interpreter()->builtinObjectPrototype()) {} 00143 00144 Value Screen::get(ExecState *exec, const Identifier &p) const 00145 { 00146 #ifdef KJS_VERBOSE 00147 kdDebug(6070) << "Screen::get " << p.qstring() << endl; 00148 #endif 00149 return lookupGetValue<Screen,ObjectImp>(exec,p,&ScreenTable,this); 00150 } 00151 00152 Value Screen::getValueProperty(ExecState *exec, int token) const 00153 { 00154 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00155 KWinModule info(0, KWinModule::INFO_DESKTOP); 00156 #endif 00157 QWidget *thisWidget = Window::retrieveActive(exec)->part()->view(); 00158 QRect sg = KGlobalSettings::desktopGeometry(thisWidget); 00159 00160 switch( token ) { 00161 case Height: 00162 return Number(sg.height()); 00163 case Width: 00164 return Number(sg.width()); 00165 case ColorDepth: 00166 case PixelDepth: { 00167 QPaintDeviceMetrics m(QApplication::desktop()); 00168 return Number(m.depth()); 00169 } 00170 case AvailLeft: { 00171 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00172 QRect clipped = info.workArea().intersect(sg); 00173 return Number(clipped.x()-sg.x()); 00174 #else 00175 return Number(10); 00176 #endif 00177 } 00178 case AvailTop: { 00179 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00180 QRect clipped = info.workArea().intersect(sg); 00181 return Number(clipped.y()-sg.y()); 00182 #else 00183 return Number(10); 00184 #endif 00185 } 00186 case AvailHeight: { 00187 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00188 QRect clipped = info.workArea().intersect(sg); 00189 return Number(clipped.height()); 00190 #else 00191 return Number(100); 00192 #endif 00193 } 00194 case AvailWidth: { 00195 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00196 QRect clipped = info.workArea().intersect(sg); 00197 return Number(clipped.width()); 00198 #else 00199 return Number(100); 00200 #endif 00201 } 00202 default: 00203 kdDebug(6070) << "WARNING: Screen::getValueProperty unhandled token " << token << endl; 00204 return Undefined(); 00205 } 00206 } 00207 00209 00210 const ClassInfo Window::info = { "Window", 0, &WindowTable, 0 }; 00211 00212 /* 00213 @begin WindowTable 87 00214 closed Window::Closed DontDelete|ReadOnly 00215 crypto Window::Crypto DontDelete|ReadOnly 00216 defaultStatus Window::DefaultStatus DontDelete 00217 defaultstatus Window::DefaultStatus DontDelete 00218 status Window::Status DontDelete 00219 document Window::Document DontDelete|ReadOnly 00220 Node Window::Node DontDelete 00221 Event Window::EventCtor DontDelete 00222 Range Window::Range DontDelete 00223 NodeFilter Window::NodeFilter DontDelete 00224 DOMException Window::DOMException DontDelete 00225 CSSRule Window::CSSRule DontDelete 00226 frames Window::Frames DontDelete|ReadOnly 00227 history Window::_History DontDelete|ReadOnly 00228 external Window::_External DontDelete|ReadOnly 00229 event Window::Event DontDelete|ReadOnly 00230 innerHeight Window::InnerHeight DontDelete|ReadOnly 00231 innerWidth Window::InnerWidth DontDelete|ReadOnly 00232 length Window::Length DontDelete|ReadOnly 00233 location Window::_Location DontDelete 00234 name Window::Name DontDelete 00235 navigator Window::_Navigator DontDelete|ReadOnly 00236 clientInformation Window::ClientInformation DontDelete|ReadOnly 00237 konqueror Window::_Konqueror DontDelete|ReadOnly 00238 offscreenBuffering Window::OffscreenBuffering DontDelete|ReadOnly 00239 opener Window::Opener DontDelete|ReadOnly 00240 outerHeight Window::OuterHeight DontDelete|ReadOnly 00241 outerWidth Window::OuterWidth DontDelete|ReadOnly 00242 pageXOffset Window::PageXOffset DontDelete|ReadOnly 00243 pageYOffset Window::PageYOffset DontDelete|ReadOnly 00244 parent Window::Parent DontDelete|ReadOnly 00245 personalbar Window::Personalbar DontDelete|ReadOnly 00246 screenX Window::ScreenX DontDelete|ReadOnly 00247 screenY Window::ScreenY DontDelete|ReadOnly 00248 scrollbars Window::Scrollbars DontDelete|ReadOnly 00249 scroll Window::Scroll DontDelete|Function 2 00250 scrollBy Window::ScrollBy DontDelete|Function 2 00251 scrollTo Window::ScrollTo DontDelete|Function 2 00252 moveBy Window::MoveBy DontDelete|Function 2 00253 moveTo Window::MoveTo DontDelete|Function 2 00254 resizeBy Window::ResizeBy DontDelete|Function 2 00255 resizeTo Window::ResizeTo DontDelete|Function 2 00256 self Window::Self DontDelete|ReadOnly 00257 window Window::_Window DontDelete|ReadOnly 00258 top Window::Top DontDelete|ReadOnly 00259 screen Window::_Screen DontDelete|ReadOnly 00260 Image Window::Image DontDelete|ReadOnly 00261 Option Window::Option DontDelete|ReadOnly 00262 XMLHttpRequest Window::XMLHttpRequest DontDelete|ReadOnly 00263 alert Window::Alert DontDelete|Function 1 00264 confirm Window::Confirm DontDelete|Function 1 00265 prompt Window::Prompt DontDelete|Function 2 00266 open Window::Open DontDelete|Function 3 00267 setTimeout Window::SetTimeout DontDelete|Function 2 00268 clearTimeout Window::ClearTimeout DontDelete|Function 1 00269 focus Window::Focus DontDelete|Function 0 00270 blur Window::Blur DontDelete|Function 0 00271 close Window::Close DontDelete|Function 0 00272 setInterval Window::SetInterval DontDelete|Function 2 00273 clearInterval Window::ClearInterval DontDelete|Function 1 00274 captureEvents Window::CaptureEvents DontDelete|Function 0 00275 releaseEvents Window::ReleaseEvents DontDelete|Function 0 00276 print Window::Print DontDelete|Function 0 00277 addEventListener Window::AddEventListener DontDelete|Function 3 00278 removeEventListener Window::RemoveEventListener DontDelete|Function 3 00279 # IE extension 00280 navigate Window::Navigate DontDelete|Function 1 00281 # Mozilla extension 00282 sidebar Window::SideBar DontDelete|ReadOnly 00283 00284 # Warning, when adding a function to this object you need to add a case in Window::get 00285 00286 # Event handlers 00287 # IE also has: onactivate, onbefore/afterprint, onbeforedeactivate/unload, oncontrolselect, 00288 # ondeactivate, onhelp, onmovestart/end, onresizestart/end, onscroll. 00289 # It doesn't have onabort, onchange, ondragdrop (but NS has that last one). 00290 onabort Window::Onabort DontDelete 00291 onblur Window::Onblur DontDelete 00292 onchange Window::Onchange DontDelete 00293 onclick Window::Onclick DontDelete 00294 ondblclick Window::Ondblclick DontDelete 00295 ondragdrop Window::Ondragdrop DontDelete 00296 onerror Window::Onerror DontDelete 00297 onfocus Window::Onfocus DontDelete 00298 onkeydown Window::Onkeydown DontDelete 00299 onkeypress Window::Onkeypress DontDelete 00300 onkeyup Window::Onkeyup DontDelete 00301 onload Window::Onload DontDelete 00302 onmousedown Window::Onmousedown DontDelete 00303 onmousemove Window::Onmousemove DontDelete 00304 onmouseout Window::Onmouseout DontDelete 00305 onmouseover Window::Onmouseover DontDelete 00306 onmouseup Window::Onmouseup DontDelete 00307 onmove Window::Onmove DontDelete 00308 onreset Window::Onreset DontDelete 00309 onresize Window::Onresize DontDelete 00310 onselect Window::Onselect DontDelete 00311 onsubmit Window::Onsubmit DontDelete 00312 onunload Window::Onunload DontDelete 00313 @end 00314 */ 00315 IMPLEMENT_PROTOFUNC_DOM(WindowFunc) 00316 00317 Window::Window(KHTMLPart *p) 00318 : ObjectImp(/*no proto*/), m_part(p), screen(0), history(0), external(0), m_frames(0), loc(0), m_evt(0) 00319 { 00320 winq = new WindowQObject(this); 00321 //kdDebug(6070) << "Window::Window this=" << this << " part=" << m_part << " " << m_part->name() << endl; 00322 } 00323 00324 Window::~Window() 00325 { 00326 delete winq; 00327 } 00328 00329 Window *Window::retrieveWindow(KHTMLPart *p) 00330 { 00331 Object obj = Object::dynamicCast( retrieve( p ) ); 00332 #ifndef NDEBUG 00333 // obj should never be null, except when javascript has been disabled in that part. 00334 if ( p && p->jScriptEnabled() ) 00335 { 00336 assert( !obj.isNull() ); 00337 #ifndef QWS 00338 assert( dynamic_cast<KJS::Window*>(obj.imp()) ); // type checking 00339 #endif 00340 } 00341 #endif 00342 if ( obj.isNull() ) // JS disabled 00343 return 0; 00344 return static_cast<KJS::Window*>(obj.imp()); 00345 } 00346 00347 Window *Window::retrieveActive(ExecState *exec) 00348 { 00349 ValueImp *imp = exec->interpreter()->globalObject().imp(); 00350 assert( imp ); 00351 #ifndef QWS 00352 assert( dynamic_cast<KJS::Window*>(imp) ); 00353 #endif 00354 return static_cast<KJS::Window*>(imp); 00355 } 00356 00357 Value Window::retrieve(KHTMLPart *p) 00358 { 00359 assert(p); 00360 KJSProxy *proxy = p->jScript(); 00361 if (proxy) { 00362 #ifdef KJS_VERBOSE 00363 kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' interpreter=" << proxy->interpreter() << " window=" << proxy->interpreter()->globalObject().imp() << endl; 00364 #endif 00365 return proxy->interpreter()->globalObject(); // the Global object is the "window" 00366 } else { 00367 #ifdef KJS_VERBOSE 00368 kdDebug(6070) << "Window::retrieve part=" << p << " '" << p->name() << "' no jsproxy." << endl; 00369 #endif 00370 return Undefined(); // This can happen with JS disabled on the domain of that window 00371 } 00372 } 00373 00374 Location *Window::location() const 00375 { 00376 if (!loc) 00377 const_cast<Window*>(this)->loc = new Location(m_part); 00378 return loc; 00379 } 00380 00381 ObjectImp* Window::frames( ExecState* exec ) const 00382 { 00383 return m_frames ? m_frames : 00384 (const_cast<Window*>(this)->m_frames = new FrameArray(exec,m_part)); 00385 } 00386 00387 // reference our special objects during garbage collection 00388 void Window::mark() 00389 { 00390 ObjectImp::mark(); 00391 if (screen && !screen->marked()) 00392 screen->mark(); 00393 if (history && !history->marked()) 00394 history->mark(); 00395 if (external && !external->marked()) 00396 external->mark(); 00397 if (m_frames && !m_frames->marked()) 00398 m_frames->mark(); 00399 //kdDebug(6070) << "Window::mark " << this << " marking loc=" << loc << endl; 00400 if (loc && !loc->marked()) 00401 loc->mark(); 00402 if (winq) 00403 winq->mark(); 00404 } 00405 00406 bool Window::hasProperty(ExecState *exec, const Identifier &p) const 00407 { 00408 // we don't want any operations on a closed window 00409 if (m_part.isNull()) 00410 return ( p == "closed" ); 00411 00412 if (ObjectImp::hasProperty(exec, p)) 00413 return true; 00414 00415 if (Lookup::findEntry(&WindowTable, p)) 00416 return true; 00417 00418 QString q = p.qstring(); 00419 if (m_part->findFrame(p.qstring())) 00420 return true; 00421 // allow window[1] or parent[1] etc. (#56983) 00422 bool ok; 00423 unsigned int i = p.toArrayIndex(&ok); 00424 if (ok) { 00425 QPtrList<KParts::ReadOnlyPart> frames = m_part->frames(); 00426 unsigned int len = frames.count(); 00427 if (i < len) 00428 return true; 00429 } 00430 00431 // allow shortcuts like 'Image1' instead of document.images.Image1 00432 if (m_part->document().isHTMLDocument()) { // might be XML 00433 DOM::HTMLDocument doc = m_part->htmlDocument(); 00434 // Keep in sync with tryGet 00435 NamedTagLengthDeterminer::TagLength tags[3] = { 00436 {ID_IMG, 0, 0L}, {ID_FORM, 0, 0L}, {ID_APPLET, 0, 0L} 00437 }; 00438 NamedTagLengthDeterminer(p.string(), tags, 3)(doc.handle()); 00439 for (int i = 0; i < 3; i++) 00440 if (tags[i].length > 0) 00441 return true; 00442 00443 return !doc.getElementById(p.string()).isNull(); 00444 } 00445 00446 return false; 00447 } 00448 00449 UString Window::toString(ExecState *) const 00450 { 00451 return "[object Window]"; 00452 } 00453 00454 Value Window::get(ExecState *exec, const Identifier &p) const 00455 { 00456 #ifdef KJS_VERBOSE 00457 kdDebug(6070) << "Window("<<this<<")::get " << p.qstring() << endl; 00458 #endif 00459 // we don't want any operations on a closed window 00460 if (m_part.isNull()) { 00461 if ( p == "closed" ) 00462 return Boolean( true ); 00463 return Undefined(); 00464 } 00465 00466 // Look for overrides first 00467 Value val = ObjectImp::get(exec, p); 00468 if (!val.isA(UndefinedType)) { 00469 //kdDebug(6070) << "Window::get found dynamic property '" << p.ascii() << "'" << endl; 00470 return isSafeScript(exec) ? val : Undefined(); 00471 } 00472 00473 const HashEntry* entry = Lookup::findEntry(&WindowTable, p); 00474 00475 // properties that work on all windows 00476 if (entry) { 00477 switch(entry->value) { 00478 case Closed: 00479 return Boolean( false ); 00480 case _Location: 00481 // No isSafeScript test here, we must be able to _set_ location.href (#49819) 00482 return Value(location()); 00483 case Frames: 00484 return Value(frames(exec)); 00485 case Opener: 00486 if (!m_part->opener()) 00487 return Null(); // ### a null Window might be better, but == null 00488 else // doesn't work yet 00489 return retrieve(m_part->opener()); 00490 case Parent: 00491 return retrieve(m_part->parentPart() ? m_part->parentPart() : (KHTMLPart*)m_part); 00492 case _Window: 00493 case Self: 00494 return retrieve(m_part); 00495 case Top: { 00496 KHTMLPart *p = m_part; 00497 while (p->parentPart()) 00498 p = p->parentPart(); 00499 return retrieve(p); 00500 } 00501 case Alert: 00502 case Confirm: 00503 case Prompt: 00504 case Open: 00505 case Focus: 00506 case Blur: 00507 return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr); 00508 default: 00509 break; 00510 } 00511 } 00512 00513 // properties that only work on safe windows 00514 if (isSafeScript(exec) && entry) 00515 { 00516 //kdDebug(6070) << "token: " << entry->value << endl; 00517 switch( entry->value ) { 00518 case Crypto: 00519 return Undefined(); // ### 00520 case DefaultStatus: 00521 return String(UString(m_part->jsDefaultStatusBarText())); 00522 case Status: 00523 return String(UString(m_part->jsStatusBarText())); 00524 case Document: 00525 if (m_part->document().isNull()) { 00526 kdDebug(6070) << "Document.write: adding <HTML><BODY> to create document" << endl; 00527 m_part->begin(); 00528 m_part->write("<HTML><BODY>"); 00529 m_part->end(); 00530 } 00531 return getDOMNode(exec,m_part->document()); 00532 case Node: 00533 return getNodeConstructor(exec); 00534 case Range: 00535 return getRangeConstructor(exec); 00536 case NodeFilter: 00537 return getNodeFilterConstructor(exec); 00538 case DOMException: 00539 return getDOMExceptionConstructor(exec); 00540 case CSSRule: 00541 return getCSSRuleConstructor(exec); 00542 case EventCtor: 00543 return getEventConstructor(exec); 00544 case _History: 00545 return Value(history ? history : 00546 (const_cast<Window*>(this)->history = new History(exec,m_part))); 00547 00548 case _External: 00549 return Value(external ? external : 00550 (const_cast<Window*>(this)->external = new External(exec,m_part))); 00551 00552 case Event: 00553 if (m_evt) 00554 return getDOMEvent(exec,*m_evt); 00555 else { 00556 #ifdef KJS_VERBOSE 00557 kdDebug(6070) << "WARNING: window(" << this << "," << m_part->name() << ").event, no event!" << endl; 00558 #endif 00559 return Undefined(); 00560 } 00561 case InnerHeight: 00562 if (!m_part->view()) 00563 return Undefined(); 00564 khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size 00565 return Number(m_part->view()->visibleHeight()); 00566 case InnerWidth: 00567 if (!m_part->view()) 00568 return Undefined(); 00569 khtml::RenderWidget::flushWidgetResizes(); // make sure frames have their final size 00570 return Number(m_part->view()->visibleWidth()); 00571 case Length: 00572 return Number(m_part->frames().count()); 00573 case Name: 00574 return String(m_part->name()); 00575 case SideBar: 00576 return Value(new MozillaSidebarExtension(exec, m_part)); 00577 case _Navigator: 00578 case ClientInformation: { 00579 // Store the navigator in the object so we get the same one each time. 00580 Value nav( new Navigator(exec, m_part) ); 00581 const_cast<Window *>(this)->put(exec, "navigator", nav, DontDelete|ReadOnly|Internal); 00582 const_cast<Window *>(this)->put(exec, "clientInformation", nav, DontDelete|ReadOnly|Internal); 00583 return nav; 00584 } 00585 #ifdef Q_WS_QWS 00586 case _Konqueror: { 00587 Value k( new Konqueror(exec, m_part) ); 00588 const_cast<Window *>(this)->put(exec, "konqueror", k, DontDelete|ReadOnly|Internal); 00589 return k; 00590 } 00591 #endif 00592 case OffscreenBuffering: 00593 return Boolean(true); 00594 case OuterHeight: 00595 case OuterWidth: 00596 { 00597 if (!m_part->widget()) 00598 return Number(0); 00599 KWin::WindowInfo inf = KWin::windowInfo(m_part->widget()->topLevelWidget()->winId()); 00600 return Number(entry->value == OuterHeight ? 00601 inf.geometry().height() : inf.geometry().width()); 00602 } 00603 case PageXOffset: 00604 return Number(m_part->view()->contentsX()); 00605 case PageYOffset: 00606 return Number(m_part->view()->contentsY()); 00607 case Personalbar: 00608 return Undefined(); // ### 00609 case ScreenLeft: 00610 case ScreenX: { 00611 if (!m_part->view()) 00612 return Undefined(); 00613 QRect sg = KGlobalSettings::desktopGeometry(m_part->view()); 00614 return Number(m_part->view()->mapToGlobal(QPoint(0,0)).x() + sg.x()); 00615 } 00616 case ScreenTop: 00617 case ScreenY: { 00618 if (!m_part->view()) 00619 return Undefined(); 00620 QRect sg = KGlobalSettings::desktopGeometry(m_part->view()); 00621 return Number(m_part->view()->mapToGlobal(QPoint(0,0)).y() + sg.y()); 00622 } 00623 case ScrollX: { 00624 if (!m_part->view()) 00625 return Undefined(); 00626 return Number(m_part->view()->contentsX()); 00627 } 00628 case ScrollY: { 00629 if (!m_part->view()) 00630 return Undefined(); 00631 return Number(m_part->view()->contentsY()); 00632 } 00633 case Scrollbars: 00634 return Undefined(); // ### 00635 case _Screen: 00636 return Value(screen ? screen : 00637 (const_cast<Window*>(this)->screen = new Screen(exec))); 00638 case Image: 00639 return Value(new ImageConstructorImp(exec, m_part->document())); 00640 case Option: 00641 return Value(new OptionConstructorImp(exec, m_part->document())); 00642 case XMLHttpRequest: 00643 return Value( new XMLHttpRequestConstructorImp( exec,m_part->document() ) ); 00644 case Close: 00645 case Scroll: // compatibility 00646 case ScrollBy: 00647 case ScrollTo: 00648 case MoveBy: 00649 case MoveTo: 00650 case ResizeBy: 00651 case ResizeTo: 00652 case CaptureEvents: 00653 case ReleaseEvents: 00654 case AddEventListener: 00655 case RemoveEventListener: 00656 case SetTimeout: 00657 case ClearTimeout: 00658 case SetInterval: 00659 case ClearInterval: 00660 case Print: 00661 return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr); 00662 // IE extension 00663 case Navigate: 00664 // Disabled in NS-compat mode. Supported by default - can't hurt, unless someone uses 00665 // if (navigate) to test for IE (unlikely). 00666 if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat ) 00667 return Undefined(); 00668 return lookupOrCreateFunction<WindowFunc>(exec,p,this,entry->value,entry->params,entry->attr); 00669 case Onabort: 00670 return getListener(exec,DOM::EventImpl::ABORT_EVENT); 00671 case Onblur: 00672 return getListener(exec,DOM::EventImpl::BLUR_EVENT); 00673 case Onchange: 00674 return getListener(exec,DOM::EventImpl::CHANGE_EVENT); 00675 case Onclick: 00676 return getListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT); 00677 case Ondblclick: 00678 return getListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT); 00679 case Ondragdrop: 00680 return getListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT); 00681 case Onerror: 00682 return getListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT); 00683 case Onfocus: 00684 return getListener(exec,DOM::EventImpl::FOCUS_EVENT); 00685 case Onkeydown: 00686 return getListener(exec,DOM::EventImpl::KEYDOWN_EVENT); 00687 case Onkeypress: 00688 return getListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT); 00689 case Onkeyup: 00690 return getListener(exec,DOM::EventImpl::KEYUP_EVENT); 00691 case Onload: 00692 return getListener(exec,DOM::EventImpl::LOAD_EVENT); 00693 case Onmousedown: 00694 return getListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT); 00695 case Onmousemove: 00696 return getListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT); 00697 case Onmouseout: 00698 return getListener(exec,DOM::EventImpl::MOUSEOUT_EVENT); 00699 case Onmouseover: 00700 return getListener(exec,DOM::EventImpl::MOUSEOVER_EVENT); 00701 case Onmouseup: 00702 return getListener(exec,DOM::EventImpl::MOUSEUP_EVENT); 00703 case Onmove: 00704 return getListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT); 00705 case Onreset: 00706 return getListener(exec,DOM::EventImpl::RESET_EVENT); 00707 case Onresize: 00708 return getListener(exec,DOM::EventImpl::RESIZE_EVENT); 00709 case Onselect: 00710 return getListener(exec,DOM::EventImpl::SELECT_EVENT); 00711 case Onsubmit: 00712 return getListener(exec,DOM::EventImpl::SUBMIT_EVENT); 00713 case Onunload: 00714 return getListener(exec,DOM::EventImpl::UNLOAD_EVENT); 00715 } 00716 } 00717 KHTMLPart *kp = m_part->findFrame( p.qstring() ); 00718 if (kp) 00719 return retrieve(kp); 00720 00721 // allow window[1] or parent[1] etc. (#56983) 00722 bool ok; 00723 unsigned int i = p.toArrayIndex(&ok); 00724 if (ok) { 00725 QPtrList<KParts::ReadOnlyPart> frames = m_part->frames(); 00726 unsigned int len = frames.count(); 00727 if (i < len) { 00728 KParts::ReadOnlyPart* frame = frames.at(i); 00729 if (frame && ::qt_cast<KHTMLPart*>(frame)) { 00730 KHTMLPart *khtml = static_cast<KHTMLPart*>(frame); 00731 return Window::retrieve(khtml); 00732 } 00733 } 00734 } 00735 00736 // allow shortcuts like 'Image1' instead of document.images.Image1 00737 if (isSafeScript(exec) && 00738 m_part->document().isHTMLDocument()) { // might be XML 00739 // This is only for images, forms and applets, see KJS::HTMLDocument::tryGet 00740 DOM::HTMLDocument doc = m_part->htmlDocument(); 00741 NamedTagLengthDeterminer::TagLength tags[3] = { 00742 {ID_IMG, 0, 0L}, {ID_FORM, 0, 0L}, {ID_APPLET, 0, 0L} 00743 }; 00744 NamedTagLengthDeterminer(p.string(), tags, 3)(doc.handle()); 00745 for (int i = 0; i < 3; i++) 00746 if (tags[i].length > 0) { 00747 if (tags[i].length == 1) 00748 return getDOMNode(exec, tags[i].last); 00749 // Get all the items with the same name 00750 return getDOMNodeList(exec, DOM::NodeList(new DOM::NamedTagNodeListImpl(doc.handle(), tags[i].id, p.string()))); 00751 } 00752 00753 DOM::Element element = doc.getElementById(p.string() ); 00754 if ( !element.isNull() ) 00755 return getDOMNode(exec, element ); 00756 } 00757 00758 // This isn't necessarily a bug. Some code uses if(!window.blah) window.blah=1 00759 // But it can also mean something isn't loaded or implemented, hence the WARNING to help grepping. 00760 #ifdef KJS_VERBOSE 00761 kdDebug(6070) << "WARNING: Window::get property not found: " << p.qstring() << endl; 00762 #endif 00763 return Undefined(); 00764 } 00765 00766 void Window::put(ExecState* exec, const Identifier &propertyName, const Value &value, int attr) 00767 { 00768 // Called by an internal KJS call (e.g. InterpreterImp's constructor) ? 00769 // If yes, save time and jump directly to ObjectImp. 00770 if ( (attr != None && attr != DontDelete) || 00771 // Same thing if we have a local override (e.g. "var location") 00772 ( isSafeScript( exec ) && ObjectImp::getDirect(propertyName) ) ) 00773 { 00774 ObjectImp::put( exec, propertyName, value, attr ); 00775 return; 00776 } 00777 00778 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName); 00779 if (entry) 00780 { 00781 #ifdef KJS_VERBOSE 00782 kdDebug(6070) << "Window("<<this<<")::put " << propertyName.qstring() << endl; 00783 #endif 00784 switch( entry->value ) { 00785 case Status: { 00786 if (isSafeScript(exec) && m_part->settings()->windowStatusPolicy(m_part->url().host()) 00787 == KHTMLSettings::KJSWindowStatusAllow) { 00788 String s = value.toString(exec); 00789 m_part->setJSStatusBarText(s.value().qstring()); 00790 } 00791 return; 00792 } 00793 case DefaultStatus: { 00794 if (isSafeScript(exec) && m_part->settings()->windowStatusPolicy(m_part->url().host()) 00795 == KHTMLSettings::KJSWindowStatusAllow) { 00796 String s = value.toString(exec); 00797 m_part->setJSDefaultStatusBarText(s.value().qstring()); 00798 } 00799 return; 00800 } 00801 case _Location: 00802 goURL(exec, value.toString(exec).qstring(), false /*don't lock history*/); 00803 return; 00804 case Onabort: 00805 if (isSafeScript(exec)) 00806 setListener(exec, DOM::EventImpl::ABORT_EVENT,value); 00807 return; 00808 case Onblur: 00809 if (isSafeScript(exec)) 00810 setListener(exec, DOM::EventImpl::BLUR_EVENT,value); 00811 return; 00812 case Onchange: 00813 if (isSafeScript(exec)) 00814 setListener(exec, DOM::EventImpl::CHANGE_EVENT,value); 00815 return; 00816 case Onclick: 00817 if (isSafeScript(exec)) 00818 setListener(exec,DOM::EventImpl::KHTML_ECMA_CLICK_EVENT,value); 00819 return; 00820 case Ondblclick: 00821 if (isSafeScript(exec)) 00822 setListener(exec,DOM::EventImpl::KHTML_ECMA_DBLCLICK_EVENT,value); 00823 return; 00824 case Ondragdrop: 00825 if (isSafeScript(exec)) 00826 setListener(exec,DOM::EventImpl::KHTML_DRAGDROP_EVENT,value); 00827 return; 00828 case Onerror: 00829 if (isSafeScript(exec)) 00830 setListener(exec,DOM::EventImpl::KHTML_ERROR_EVENT,value); 00831 return; 00832 case Onfocus: 00833 if (isSafeScript(exec)) 00834 setListener(exec,DOM::EventImpl::FOCUS_EVENT,value); 00835 return; 00836 case Onkeydown: 00837 if (isSafeScript(exec)) 00838 setListener(exec,DOM::EventImpl::KEYDOWN_EVENT,value); 00839 return; 00840 case Onkeypress: 00841 if (isSafeScript(exec)) 00842 setListener(exec,DOM::EventImpl::KHTML_KEYPRESS_EVENT,value); 00843 return; 00844 case Onkeyup: 00845 if (isSafeScript(exec)) 00846 setListener(exec,DOM::EventImpl::KEYUP_EVENT,value); 00847 return; 00848 case Onload: 00849 if (isSafeScript(exec)) 00850 setListener(exec,DOM::EventImpl::LOAD_EVENT,value); 00851 return; 00852 case Onmousedown: 00853 if (isSafeScript(exec)) 00854 setListener(exec,DOM::EventImpl::MOUSEDOWN_EVENT,value); 00855 return; 00856 case Onmousemove: 00857 if (isSafeScript(exec)) 00858 setListener(exec,DOM::EventImpl::MOUSEMOVE_EVENT,value); 00859 return; 00860 case Onmouseout: 00861 if (isSafeScript(exec)) 00862 setListener(exec,DOM::EventImpl::MOUSEOUT_EVENT,value); 00863 return; 00864 case Onmouseover: 00865 if (isSafeScript(exec)) 00866 setListener(exec,DOM::EventImpl::MOUSEOVER_EVENT,value); 00867 return; 00868 case Onmouseup: 00869 if (isSafeScript(exec)) 00870 setListener(exec,DOM::EventImpl::MOUSEUP_EVENT,value); 00871 return; 00872 case Onmove: 00873 if (isSafeScript(exec)) 00874 setListener(exec,DOM::EventImpl::KHTML_MOVE_EVENT,value); 00875 return; 00876 case Onreset: 00877 if (isSafeScript(exec)) 00878 setListener(exec,DOM::EventImpl::RESET_EVENT,value); 00879 return; 00880 case Onresize: 00881 if (isSafeScript(exec)) 00882 setListener(exec,DOM::EventImpl::RESIZE_EVENT,value); 00883 return; 00884 case Onselect: 00885 if (isSafeScript(exec)) 00886 setListener(exec,DOM::EventImpl::SELECT_EVENT,value); 00887 return; 00888 case Onsubmit: 00889 if (isSafeScript(exec)) 00890 setListener(exec,DOM::EventImpl::SUBMIT_EVENT,value); 00891 return; 00892 case Onunload: 00893 if (isSafeScript(exec)) 00894 setListener(exec,DOM::EventImpl::UNLOAD_EVENT,value); 00895 return; 00896 case Name: 00897 if (isSafeScript(exec)) 00898 m_part->setName( value.toString(exec).qstring().local8Bit().data() ); 00899 return; 00900 default: 00901 break; 00902 } 00903 } 00904 if (isSafeScript(exec)) { 00905 //kdDebug(6070) << "Window("<<this<<")::put storing " << propertyName.qstring() << endl; 00906 ObjectImp::put(exec, propertyName, value, attr); 00907 } 00908 } 00909 00910 bool Window::toBoolean(ExecState *) const 00911 { 00912 return !m_part.isNull(); 00913 } 00914 00915 void Window::scheduleClose() 00916 { 00917 kdDebug(6070) << "Window::scheduleClose window.close() " << m_part << endl; 00918 Q_ASSERT(winq); 00919 QTimer::singleShot( 0, winq, SLOT( timeoutClose() ) ); 00920 } 00921 00922 void Window::closeNow() 00923 { 00924 if (!m_part.isNull()) 00925 { 00926 //kdDebug(6070) << k_funcinfo << " -> closing window" << endl; 00927 // We want to make sure that window.open won't find this part by name. 00928 m_part->setName( 0 ); 00929 m_part->deleteLater(); 00930 m_part = 0; 00931 } else 00932 kdDebug(6070) << k_funcinfo << "part is deleted already" << endl; 00933 } 00934 00935 void Window::afterScriptExecution() 00936 { 00937 DOM::DocumentImpl::updateDocumentsRendering(); 00938 QValueList<DelayedAction> delayedActions = m_delayed; 00939 m_delayed.clear(); 00940 QValueList<DelayedAction>::Iterator it = delayedActions.begin(); 00941 for ( ; it != delayedActions.end() ; ++it ) 00942 { 00943 switch ((*it).actionId) { 00944 case DelayedClose: 00945 scheduleClose(); 00946 return; // stop here, in case of multiple actions 00947 case DelayedGoHistory: 00948 goHistory( (*it).param.toInt() ); 00949 break; 00950 case NullAction: 00951 // FIXME: anything needs to be done here? This is warning anyways. 00952 break; 00953 }; 00954 } 00955 } 00956 00957 bool Window::checkIsSafeScript(KHTMLPart *activePart) const 00958 { 00959 if (m_part.isNull()) { // part deleted ? can't grant access 00960 kdDebug(6070) << "Window::isSafeScript: accessing deleted part !" << endl; 00961 return false; 00962 } 00963 if (!activePart) { 00964 kdDebug(6070) << "Window::isSafeScript: current interpreter's part is 0L!" << endl; 00965 return false; 00966 } 00967 if ( activePart == m_part ) // Not calling from another frame, no problem. 00968 return true; 00969 00970 if ( m_part->document().isNull() ) 00971 return true; // allow to access a window that was just created (e.g. with window.open("about:blank")) 00972 00973 DOM::HTMLDocument thisDocument = m_part->htmlDocument(); 00974 if ( thisDocument.isNull() ) { 00975 kdDebug(6070) << "Window::isSafeScript: trying to access an XML document !?" << endl; 00976 return false; 00977 } 00978 00979 DOM::HTMLDocument actDocument = activePart->htmlDocument(); 00980 if ( actDocument.isNull() ) { 00981 kdDebug(6070) << "Window::isSafeScript: active part has no document!" << endl; 00982 return false; 00983 } 00984 DOM::DOMString actDomain = actDocument.domain(); 00985 DOM::DOMString thisDomain = thisDocument.domain(); 00986 00987 if ( actDomain == thisDomain ) { 00988 #ifdef KJS_VERBOSE 00989 kdDebug(6070) << "JavaScript: access granted, domain is '" << actDomain.string() << "'" << endl; 00990 #endif 00991 return true; 00992 } 00993 00994 kdDebug(6070) << "WARNING: JavaScript: access denied for current frame '" << actDomain.string() << "' to frame '" << thisDomain.string() << "'" << endl; 00995 // TODO after 3.1: throw security exception (exec->setException()) 00996 return false; 00997 } 00998 00999 void Window::setListener(ExecState *exec, int eventId, Value func) 01000 { 01001 if (!isSafeScript(exec)) 01002 return; 01003 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle()); 01004 if (!doc) 01005 return; 01006 01007 doc->setWindowEventListener(eventId,getJSEventListener(func,true)); 01008 } 01009 01010 Value Window::getListener(ExecState *exec, int eventId) const 01011 { 01012 if (!isSafeScript(exec)) 01013 return Undefined(); 01014 DOM::DocumentImpl *doc = static_cast<DOM::DocumentImpl*>(m_part->htmlDocument().handle()); 01015 if (!doc) 01016 return Undefined(); 01017 01018 DOM::EventListener *listener = doc->getWindowEventListener(eventId); 01019 if (listener) 01020 return static_cast<JSEventListener*>(listener)->listenerObj(); 01021 else 01022 return Null(); 01023 } 01024 01025 01026 JSEventListener *Window::getJSEventListener(const Value& val, bool html) 01027 { 01028 // This function is so hot that it's worth coding it directly with imps. 01029 if (val.type() != ObjectType) 01030 return 0; 01031 ObjectImp *listenerObject = static_cast<ObjectImp *>(val.imp()); 01032 01033 JSEventListener *existingListener = jsEventListeners[listenerObject]; 01034 if (existingListener) 01035 return existingListener; 01036 01037 // Note that the JSEventListener constructor adds it to our jsEventListeners list 01038 return new JSEventListener(Object(listenerObject), Object(this), html); 01039 } 01040 01041 void Window::clear( ExecState *exec ) 01042 { 01043 delete winq; 01044 winq = 0L; 01045 // Get rid of everything, those user vars could hold references to DOM nodes 01046 deleteAllProperties( exec ); 01047 01048 // Break the dependency between the listeners and their object 01049 QPtrDictIterator<JSEventListener> it(jsEventListeners); 01050 for (; it.current(); ++it) 01051 it.current()->clear(); 01052 // Forget about the listeners (the DOM::NodeImpls will delete them) 01053 jsEventListeners.clear(); 01054 01055 if (!m_part.isNull()) { 01056 KJSProxy* proxy = m_part->jScript(); 01057 if (proxy) // i.e. JS not disabled 01058 { 01059 winq = new WindowQObject(this); 01060 // Now recreate a working global object for the next URL that will use us 01061 KJS::Interpreter *interpreter = proxy->interpreter(); 01062 interpreter->initGlobalObject(); 01063 } 01064 } 01065 } 01066 01067 void Window::setCurrentEvent( DOM::Event *evt ) 01068 { 01069 m_evt = evt; 01070 //kdDebug(6070) << "Window " << this << " (part=" << m_part << ")::setCurrentEvent m_evt=" << evt << endl; 01071 } 01072 01073 void Window::goURL(ExecState* exec, const QString& url, bool lockHistory) 01074 { 01075 Window* active = Window::retrieveActive(exec); 01076 // Complete the URL using the "active part" (running interpreter) 01077 if (active->part()) { 01078 if (url[0] == QChar('#')) { 01079 m_part->gotoAnchor(url.mid(1)); 01080 } else { 01081 QString dstUrl = active->part()->htmlDocument().completeURL(url).string(); 01082 KURL dst( dstUrl ); 01083 KURL partURL( m_part->url() ); 01084 // Remove refs for the comparison 01085 dst.setRef( QString::null ); 01086 partURL.setRef( QString::null ); 01087 kdDebug(6070) << "Window::goURL dstUrl=" << dst.prettyURL() << " partURL=" << partURL.prettyURL() 01088 << " identical: " << partURL.equals( dst, true ) << endl; 01089 01090 // check if we're allowed to inject javascript 01091 // SYNC check with khtml_part.cpp::slotRedirect! 01092 if ( isSafeScript(exec) || 01093 dstUrl.find(QString::fromLatin1("javascript:"), 0, false) != 0 ) 01094 m_part->scheduleRedirection(-1, 01095 dstUrl, 01096 lockHistory); 01097 } 01098 } 01099 } 01100 01101 void Window::delayedGoHistory( int steps ) 01102 { 01103 m_delayed.append( DelayedAction( DelayedGoHistory, steps ) ); 01104 } 01105 01106 void Window::goHistory( int steps ) 01107 { 01108 KParts::BrowserExtension *ext = m_part->browserExtension(); 01109 if(!ext) 01110 return; 01111 KParts::BrowserInterface *iface = ext->browserInterface(); 01112 01113 if ( !iface ) 01114 return; 01115 01116 iface->callMethod( "goHistory(int)", steps ); 01117 //emit ext->goHistory(steps); 01118 } 01119 01120 void KJS::Window::resizeTo(QWidget* tl, int width, int height) 01121 { 01122 KParts::BrowserExtension *ext = m_part->browserExtension(); 01123 if (!ext) { 01124 kdDebug(6070) << "Window::resizeTo found no browserExtension" << endl; 01125 return; 01126 } 01127 01128 // Security check: within desktop limits and bigger than 100x100 (per spec) 01129 if ( width < 100 || height < 100 ) { 01130 kdDebug(6070) << "Window::resizeTo refused, window would be too small ("<<width<<","<<height<<")" << endl; 01131 return; 01132 } 01133 01134 QRect sg = KGlobalSettings::desktopGeometry(tl); 01135 01136 if ( width > sg.width() || height > sg.height() ) { 01137 kdDebug(6070) << "Window::resizeTo refused, window would be too big ("<<width<<","<<height<<")" << endl; 01138 return; 01139 } 01140 01141 // Take into account the window frame - so that (width,height) is the external window size 01142 // ### (is that correct? for window.open it's the size of the HTML area...) 01143 int deltaWidth = tl->frameGeometry().width() - tl->width(); 01144 int deltaHeight = tl->frameGeometry().height() - tl->height(); 01145 01146 kdDebug() << "resizing to " << width - deltaWidth << "x" << height - deltaHeight << endl; 01147 01148 emit ext->resizeTopLevelWidget( width - deltaWidth, height - deltaHeight ); 01149 01150 // If the window is out of the desktop, move it up/left 01151 // (maybe we should use workarea instead of sg, otherwise the window ends up below kicker) 01152 int right = tl->x() + tl->frameGeometry().width(); 01153 int bottom = tl->y() + tl->frameGeometry().height(); 01154 int moveByX = 0; 01155 int moveByY = 0; 01156 if ( right > sg.right() ) 01157 moveByX = - right + sg.right(); // always <0 01158 if ( bottom > sg.bottom() ) 01159 moveByY = - bottom + sg.bottom(); // always <0 01160 if ( moveByX || moveByY ) 01161 emit ext->moveTopLevelWidget( tl->x() + moveByX , tl->y() + moveByY ); 01162 } 01163 01164 Value Window::openWindow(ExecState *exec, const List& args) 01165 { 01166 KHTMLView *widget = m_part->view(); 01167 Value v = args[0]; 01168 QString str = v.toString(exec).qstring(); 01169 01170 // prepare arguments 01171 KURL url; 01172 if (!str.isEmpty()) 01173 { 01174 KHTMLPart* p = Window::retrieveActive(exec)->m_part; 01175 if ( p ) 01176 url = p->htmlDocument().completeURL(str).string(); 01177 if ( !p || 01178 !static_cast<DOM::DocumentImpl*>(p->htmlDocument().handle())->isURLAllowed(url.url()) ) 01179 return Undefined(); 01180 } 01181 01182 KHTMLSettings::KJSWindowOpenPolicy policy = 01183 m_part->settings()->windowOpenPolicy(m_part->url().host()); 01184 if ( policy == KHTMLSettings::KJSWindowOpenAsk ) { 01185 if ( KMessageBox::questionYesNo(widget, 01186 str.isEmpty() ? 01187 i18n( "This site is requesting to open up a new browser " 01188 "window via JavaScript.\n" 01189 "Do you want to allow this?" ) : 01190 i18n( "<qt>This site is requesting to open<p>%1</p>in a new browser window via JavaScript.<br />" 01191 "Do you want to allow this?</qt>").arg(KStringHandler::csqueeze(url.htmlURL(), 100)), 01192 i18n( "Confirmation: JavaScript Popup" ) ) == KMessageBox::Yes ) 01193 policy = KHTMLSettings::KJSWindowOpenAllow; 01194 } else if ( policy == KHTMLSettings::KJSWindowOpenSmart ) 01195 { 01196 // window.open disabled unless from a key/mouse event 01197 if (static_cast<ScriptInterpreter *>(exec->interpreter())->isWindowOpenAllowed()) 01198 policy = KHTMLSettings::KJSWindowOpenAllow; 01199 } 01200 if ( policy != KHTMLSettings::KJSWindowOpenAllow ) { 01201 return Undefined(); 01202 } else { 01203 KParts::WindowArgs winargs; 01204 01205 // scan feature argument 01206 QString features; 01207 if (args.size()>2) { 01208 features = args[2].toString(exec).qstring(); 01209 // specifying window params means false defaults 01210 winargs.menuBarVisible = false; 01211 winargs.toolBarsVisible = false; 01212 winargs.statusBarVisible = false; 01213 QStringList flist = QStringList::split(',', features); 01214 QStringList::ConstIterator it = flist.begin(); 01215 while (it != flist.end()) { 01216 QString s = *it++; 01217 QString key, val; 01218 int pos = s.find('='); 01219 if (pos >= 0) { 01220 key = s.left(pos).stripWhiteSpace().lower(); 01221 val = s.mid(pos + 1).stripWhiteSpace().lower(); 01222 QRect screen = KGlobalSettings::desktopGeometry(widget->topLevelWidget()); 01223 01224 if (key == "left" || key == "screenx") { 01225 winargs.x = (int)val.toFloat() + screen.x(); 01226 if (winargs.x < screen.x() || winargs.x > screen.right()) 01227 winargs.x = screen.x(); // only safe choice until size is determined 01228 } else if (key == "top" || key == "screeny") { 01229 winargs.y = (int)val.toFloat() + screen.y(); 01230 if (winargs.y < screen.y() || winargs.y > screen.bottom()) 01231 winargs.y = screen.y(); // only safe choice until size is determined 01232 } else if (key == "height") { 01233 winargs.height = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2; 01234 if (winargs.height > screen.height()) // should actually check workspace 01235 winargs.height = screen.height(); 01236 if (winargs.height < 100) 01237 winargs.height = 100; 01238 } else if (key == "width") { 01239 winargs.width = (int)val.toFloat() + 2*qApp->style().pixelMetric( QStyle::PM_DefaultFrameWidth ) + 2; 01240 if (winargs.width > screen.width()) // should actually check workspace 01241 winargs.width = screen.width(); 01242 if (winargs.width < 100) 01243 winargs.width = 100; 01244 } else { 01245 goto boolargs; 01246 } 01247 continue; 01248 } else { 01249 // leaving away the value gives true 01250 key = s.stripWhiteSpace().lower(); 01251 val = "1"; 01252 } 01253 boolargs: 01254 if (key == "menubar") 01255 winargs.menuBarVisible = (val == "1" || val == "yes"); 01256 else if (key == "toolbar") 01257 winargs.toolBarsVisible = (val == "1" || val == "yes"); 01258 else if (key == "location") // ### missing in WindowArgs 01259 winargs.toolBarsVisible = (val == "1" || val == "yes"); 01260 else if (key == "status" || key == "statusbar") 01261 winargs.statusBarVisible = (val == "1" || val == "yes"); 01262 else if (key == "resizable") 01263 winargs.resizable = (val == "1" || val == "yes"); 01264 else if (key == "fullscreen") 01265 winargs.fullscreen = (val == "1" || val == "yes"); 01266 } 01267 } 01268 01269 KParts::URLArgs uargs; 01270 KHTMLPart *p = m_part; 01271 uargs.frameName = args.size() > 1 ? 01272 args[1].toString(exec).qstring() 01273 : QString("_blank"); 01274 if ( uargs.frameName.lower() == "_top" ) 01275 { 01276 while ( p->parentPart() ) 01277 p = p->parentPart(); 01278 Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/); 01279 return Window::retrieve(p); 01280 } 01281 if ( uargs.frameName.lower() == "_parent" ) 01282 { 01283 if ( p->parentPart() ) 01284 p = p->parentPart(); 01285 Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/); 01286 return Window::retrieve(p); 01287 } 01288 if ( uargs.frameName.lower() == "_self") 01289 { 01290 Window::retrieveWindow(p)->goURL(exec, url.url(), false /*don't lock history*/); 01291 return Window::retrieve(p); 01292 } 01293 if ( uargs.frameName.lower() == "replace" ) 01294 { 01295 Window::retrieveWindow(p)->goURL(exec, url.url(), true /*lock history*/); 01296 return Window::retrieve(p); 01297 } 01298 uargs.serviceType = "text/html"; 01299 01300 // request window (new or existing if framename is set) 01301 KParts::ReadOnlyPart *newPart = 0L; 01302 emit p->browserExtension()->createNewWindow(KURL(), uargs,winargs,newPart); 01303 if (newPart && ::qt_cast<KHTMLPart*>(newPart)) { 01304 KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart); 01305 //qDebug("opener set to %p (this Window's part) in new Window %p (this Window=%p)",part,win,window); 01306 khtmlpart->setOpener(p); 01307 khtmlpart->setOpenedByJS(true); 01308 if (khtmlpart->document().isNull()) { 01309 khtmlpart->begin(); 01310 khtmlpart->write("<HTML><BODY>"); 01311 khtmlpart->end(); 01312 if ( p->docImpl() ) { 01313 //kdDebug(6070) << "Setting domain to " << p->docImpl()->domain().string() << endl; 01314 khtmlpart->docImpl()->setDomain( p->docImpl()->domain()); 01315 khtmlpart->docImpl()->setBaseURL( p->docImpl()->baseURL() ); 01316 } 01317 } 01318 uargs.serviceType = QString::null; 01319 if (uargs.frameName.lower() == "_blank") 01320 uargs.frameName = QString::null; 01321 if (!url.isEmpty()) 01322 emit khtmlpart->browserExtension()->openURLRequest(url,uargs); 01323 return Window::retrieve(khtmlpart); // global object 01324 } else 01325 return Undefined(); 01326 } 01327 } 01328 01329 Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) 01330 { 01331 KJS_CHECK_THIS( Window, thisObj ); 01332 Window *window = static_cast<Window *>(thisObj.imp()); 01333 QString str, str2; 01334 01335 KHTMLPart *part = window->m_part; 01336 if (!part) 01337 return Undefined(); 01338 01339 KHTMLView *widget = part->view(); 01340 Value v = args[0]; 01341 UString s = v.toString(exec); 01342 str = s.qstring(); 01343 01344 // functions that work everywhere 01345 switch(id) { 01346 case Window::Alert: 01347 if (!widget->dialogsAllowed()) 01348 return Undefined(); 01349 if ( part && part->xmlDocImpl() ) 01350 part->xmlDocImpl()->updateRendering(); 01351 KMessageBox::error(widget, QStyleSheet::convertFromPlainText(str), "JavaScript"); 01352 return Undefined(); 01353 case Window::Confirm: 01354 if (!widget->dialogsAllowed()) 01355 return Undefined(); 01356 if ( part && part->xmlDocImpl() ) 01357 part->xmlDocImpl()->updateRendering(); 01358 return Boolean((KMessageBox::warningYesNo(widget, QStyleSheet::convertFromPlainText(str), "JavaScript", 01359 KStdGuiItem::ok(), KStdGuiItem::cancel()) == KMessageBox::Yes)); 01360 case Window::Prompt: 01361 if (!widget->dialogsAllowed()) 01362 return Undefined(); 01363 if ( part && part->xmlDocImpl() ) 01364 part->xmlDocImpl()->updateRendering(); 01365 bool ok; 01366 if (args.size() >= 2) 01367 str2 = KInputDialog::getText(i18n("Prompt"), 01368 QStyleSheet::convertFromPlainText(str), 01369 args[1].toString(exec).qstring(), &ok, widget); 01370 else 01371 str2 = KInputDialog::getText(i18n("Prompt"), 01372 QStyleSheet::convertFromPlainText(str), 01373 QString::null, &ok, widget); 01374 if ( ok ) 01375 return String(str2); 01376 else 01377 return Null(); 01378 case Window::Open: 01379 return window->openWindow(exec, args); 01380 case Window::Navigate: 01381 window->goURL(exec, args[0].toString(exec).qstring(), false /*don't lock history*/); 01382 return Undefined(); 01383 case Window::Focus: { 01384 KHTMLSettings::KJSWindowFocusPolicy policy = 01385 part->settings()->windowFocusPolicy(part->url().host()); 01386 if(policy == KHTMLSettings::KJSWindowFocusAllow && widget) { 01387 widget->topLevelWidget()->raise(); 01388 widget->setActiveWindow(); 01389 } 01390 return Undefined(); 01391 } 01392 case Window::Blur: 01393 // TODO 01394 return Undefined(); 01395 }; 01396 01397 01398 // now unsafe functions.. 01399 if (!window->isSafeScript(exec)) 01400 return Undefined(); 01401 01402 switch (id) { 01403 case Window::ScrollBy: 01404 if(args.size() == 2 && widget) 01405 widget->scrollBy(args[0].toInt32(exec), args[1].toInt32(exec)); 01406 return Undefined(); 01407 case Window::Scroll: 01408 case Window::ScrollTo: 01409 if(args.size() == 2 && widget) 01410 widget->setContentsPos(args[0].toInt32(exec), args[1].toInt32(exec)); 01411 return Undefined(); 01412 case Window::MoveBy: { 01413 KHTMLSettings::KJSWindowMovePolicy policy = 01414 part->settings()->windowMovePolicy(part->url().host()); 01415 if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget) 01416 { 01417 KParts::BrowserExtension *ext = part->browserExtension(); 01418 if (ext) { 01419 QWidget * tl = widget->topLevelWidget(); 01420 QRect sg = KGlobalSettings::desktopGeometry(tl); 01421 01422 QPoint dest = tl->pos() + QPoint( args[0].toInt32(exec), args[1].toInt32(exec) ); 01423 // Security check (the spec talks about UniversalBrowserWrite to disable this check...) 01424 if ( dest.x() >= sg.x() && dest.y() >= sg.x() && 01425 dest.x()+tl->width() <= sg.width()+sg.x() && 01426 dest.y()+tl->height() <= sg.height()+sg.y() ) 01427 emit ext->moveTopLevelWidget( dest.x(), dest.y() ); 01428 } 01429 } 01430 return Undefined(); 01431 } 01432 case Window::MoveTo: { 01433 KHTMLSettings::KJSWindowMovePolicy policy = 01434 part->settings()->windowMovePolicy(part->url().host()); 01435 if(policy == KHTMLSettings::KJSWindowMoveAllow && args.size() == 2 && widget) 01436 { 01437 KParts::BrowserExtension *ext = part->browserExtension(); 01438 if (ext) { 01439 QWidget * tl = widget->topLevelWidget(); 01440 QRect sg = KGlobalSettings::desktopGeometry(tl); 01441 01442 QPoint dest( args[0].toInt32(exec)+sg.x(), args[1].toInt32(exec)+sg.y() ); 01443 // Security check (the spec talks about UniversalBrowserWrite to disable this check...) 01444 if ( dest.x() >= sg.x() && dest.y() >= sg.y() && 01445 dest.x()+tl->width() <= sg.width()+sg.x() && 01446 dest.y()+tl->height() <= sg.height()+sg.y() ) 01447 emit ext->moveTopLevelWidget( dest.x(), dest.y() ); 01448 } 01449 } 01450 return Undefined(); 01451 } 01452 case Window::ResizeBy: { 01453 KHTMLSettings::KJSWindowResizePolicy policy = 01454 part->settings()->windowResizePolicy(part->url().host()); 01455 if(policy == KHTMLSettings::KJSWindowResizeAllow 01456 && args.size() == 2 && widget) 01457 { 01458 QWidget * tl = widget->topLevelWidget(); 01459 QRect geom = tl->frameGeometry(); 01460 window->resizeTo( tl, 01461 geom.width() + args[0].toInt32(exec), 01462 geom.height() + args[1].toInt32(exec) ); 01463 } 01464 return Undefined(); 01465 } 01466 case Window::ResizeTo: { 01467 KHTMLSettings::KJSWindowResizePolicy policy = 01468 part->settings()->windowResizePolicy(part->url().host()); 01469 if(policy == KHTMLSettings::KJSWindowResizeAllow 01470 && args.size() == 2 && widget) 01471 { 01472 QWidget * tl = widget->topLevelWidget(); 01473 window->resizeTo( tl, args[0].toInt32(exec), args[1].toInt32(exec) ); 01474 } 01475 return Undefined(); 01476 } 01477 case Window::SetTimeout: 01478 case Window::SetInterval: { 01479 bool singleShot; 01480 int i; // timeout interval 01481 if (args.size() == 0) 01482 return Undefined(); 01483 if (args.size() > 1) { 01484 singleShot = (id == Window::SetTimeout); 01485 i = args[1].toInt32(exec); 01486 } else { 01487 // second parameter is missing. Emulate Mozilla behavior. 01488 singleShot = true; 01489 i = 4; 01490 } 01491 if (v.isA(StringType)) { 01492 int r = (const_cast<Window*>(window))->winq->installTimeout(Identifier(s), i, singleShot ); 01493 return Number(r); 01494 } 01495 else if (v.isA(ObjectType) && Object::dynamicCast(v).implementsCall()) { 01496 Object func = Object::dynamicCast(v); 01497 List funcArgs; 01498 ListIterator it = args.begin(); 01499 int argno = 0; 01500 while (it != args.end()) { 01501 Value arg = it++; 01502 if (argno++ >= 2) 01503 funcArgs.append(arg); 01504 } 01505 if (args.size() < 2) 01506 funcArgs.append(Number(i)); 01507 int r = (const_cast<Window*>(window))->winq->installTimeout(func, funcArgs, i, singleShot ); 01508 return Number(r); 01509 } 01510 else 01511 return Undefined(); 01512 } 01513 case Window::ClearTimeout: 01514 case Window::ClearInterval: 01515 (const_cast<Window*>(window))->winq->clearTimeout(v.toInt32(exec)); 01516 return Undefined(); 01517 case Window::Close: { 01518 /* From http://developer.netscape.com/docs/manuals/js/client/jsref/window.htm : 01519 The close method closes only windows opened by JavaScript using the open method. 01520 If you attempt to close any other window, a confirm is generated, which 01521 lets the user choose whether the window closes. 01522 This is a security feature to prevent "mail bombs" containing self.close(). 01523 However, if the window has only one document (the current one) in its 01524 session history, the close is allowed without any confirm. This is a 01525 special case for one-off windows that need to open other windows and 01526 then dispose of themselves. 01527 */ 01528 bool doClose = false; 01529 if (!part->openedByJS()) 01530 { 01531 // To conform to the SPEC, we only ask if the window 01532 // has more than one entry in the history (NS does that too). 01533 History history(exec,part); 01534 if ( history.get( exec, "length" ).toInt32(exec) <= 1 || 01535 KMessageBox::questionYesNo( window->part()->widget(), i18n("Close window?"), i18n("Confirmation Required") ) == KMessageBox::Yes ) 01536 doClose = true; 01537 } 01538 else 01539 doClose = true; 01540 01541 if (doClose) 01542 { 01543 // If this is the current window (the one the interpreter runs in), 01544 // then schedule a delayed close (so that the script terminates first). 01545 // But otherwise, close immediately. This fixes w=window.open("","name");w.close();window.open("name"); 01546 if ( Window::retrieveActive(exec) == window ) { 01547 if (widget) { 01548 // quit all dialogs of this view 01549 // this fixes 'setTimeout('self.close()',1000); alert("Hi");' crash 01550 widget->closeChildDialogs(); 01551 } 01552 //kdDebug() << "scheduling delayed close" << endl; 01553 // We'll close the window at the end of the script execution 01554 Window* w = const_cast<Window*>(window); 01555 w->m_delayed.append( Window::DelayedAction( Window::DelayedClose ) ); 01556 } else { 01557 //kdDebug() << "closing NOW" << endl; 01558 (const_cast<Window*>(window))->closeNow(); 01559 } 01560 } 01561 return Undefined(); 01562 } 01563 case Window::Print: 01564 if ( widget ) { 01565 // ### TODO emit onbeforeprint event 01566 widget->print(); 01567 // ### TODO emit onafterprint event 01568 } 01569 case Window::CaptureEvents: 01570 case Window::ReleaseEvents: 01571 // Do nothing for now. These are NS-specific legacy calls. 01572 break; 01573 case Window::AddEventListener: { 01574 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); 01575 DOM::Document doc = part->document(); 01576 if (doc.isHTMLDocument()) { 01577 DOM::HTMLDocument htmlDoc = doc; 01578 htmlDoc.body().addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec)); 01579 } 01580 else 01581 doc.addEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec)); 01582 return Undefined(); 01583 } 01584 case Window::RemoveEventListener: { 01585 JSEventListener *listener = Window::retrieveActive(exec)->getJSEventListener(args[1]); 01586 DOM::Document doc = part->document(); 01587 if (doc.isHTMLDocument()) { 01588 DOM::HTMLDocument htmlDoc = doc; 01589 htmlDoc.body().removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec)); 01590 } 01591 else 01592 doc.removeEventListener(args[0].toString(exec).string(),listener,args[2].toBoolean(exec)); 01593 return Undefined(); 01594 } 01595 break; 01596 } 01597 return Undefined(); 01598 } 01599 01601 01602 // KDE 4: Make those parameters const ... & 01603 ScheduledAction::ScheduledAction(Object _func, List _args, QTime _nextTime, int _interval, bool _singleShot, 01604 int _timerId) 01605 { 01606 //kdDebug(6070) << "ScheduledAction::ScheduledAction(isFunction) " << this << endl; 01607 func = static_cast<ObjectImp*>(_func.imp()); 01608 args = _args; 01609 isFunction = true; 01610 singleShot = _singleShot; 01611 nextTime = _nextTime; 01612 interval = _interval; 01613 executing = false; 01614 timerId = _timerId; 01615 } 01616 01617 // KDE 4: Make it const QString & 01618 ScheduledAction::ScheduledAction(QString _code, QTime _nextTime, int _interval, bool _singleShot, int _timerId) 01619 { 01620 //kdDebug(6070) << "ScheduledAction::ScheduledAction(!isFunction) " << this << endl; 01621 //func = 0; 01622 //args = 0; 01623 func = 0; 01624 code = _code; 01625 isFunction = false; 01626 singleShot = _singleShot; 01627 nextTime = _nextTime; 01628 interval = _interval; 01629 executing = false; 01630 timerId = _timerId; 01631 } 01632 01633 void ScheduledAction::execute(Window *window) 01634 { 01635 ScriptInterpreter *interpreter = static_cast<ScriptInterpreter *>(window->m_part->jScript()->interpreter()); 01636 01637 interpreter->setProcessingTimerCallback(true); 01638 01639 //kdDebug(6070) << "ScheduledAction::execute " << this << endl; 01640 if (isFunction) { 01641 if (func->implementsCall()) { 01642 // #### check this 01643 Q_ASSERT( window->m_part ); 01644 if ( window->m_part ) 01645 { 01646 KJS::Interpreter *interpreter = window->m_part->jScript()->interpreter(); 01647 ExecState *exec = interpreter->globalExec(); 01648 Q_ASSERT( window == interpreter->globalObject().imp() ); 01649 Object obj( window ); 01650 func->call(exec,obj,args); // note that call() creates its own execution state for the func call 01651 if (exec->hadException()) 01652 exec->clearException(); 01653 01654 // Update our document's rendering following the execution of the timeout callback. 01655 window->m_part->document().updateRendering(); 01656 } 01657 } 01658 } 01659 else { 01660 window->m_part->executeScript(DOM::Node(), code); 01661 } 01662 01663 interpreter->setProcessingTimerCallback(false); 01664 } 01665 01666 void ScheduledAction::mark() 01667 { 01668 if (func && !func->marked()) 01669 func->mark(); 01670 args.mark(); 01671 } 01672 01673 ScheduledAction::~ScheduledAction() 01674 { 01675 //kdDebug(6070) << "ScheduledAction::~ScheduledAction " << this << endl; 01676 } 01677 01679 01680 WindowQObject::WindowQObject(Window *w) 01681 : parent(w) 01682 { 01683 //kdDebug(6070) << "WindowQObject::WindowQObject " << this << endl; 01684 part = parent->m_part; 01685 if ( !part ) 01686 kdDebug(6070) << "WARNING: null part in " << k_funcinfo << endl; 01687 else 01688 connect( part, SIGNAL( destroyed() ), 01689 this, SLOT( parentDestroyed() ) ); 01690 pausedTime = 0; 01691 lastTimerId = 0; 01692 } 01693 01694 WindowQObject::~WindowQObject() 01695 { 01696 //kdDebug(6070) << "WindowQObject::~WindowQObject " << this << endl; 01697 parentDestroyed(); // reuse same code 01698 } 01699 01700 void WindowQObject::parentDestroyed() 01701 { 01702 killTimers(); 01703 01704 QPtrListIterator<ScheduledAction> it(scheduledActions); 01705 for (; it.current(); ++it) 01706 delete it.current(); 01707 scheduledActions.clear(); 01708 } 01709 01710 int WindowQObject::installTimeout(const Identifier &handler, int t, bool singleShot) 01711 { 01712 int id = ++lastTimerId; 01713 if (t < 10) t = 10; 01714 QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t); 01715 ScheduledAction *action = new ScheduledAction(handler.qstring(),nextTime,t,singleShot,id); 01716 scheduledActions.append(action); 01717 setNextTimer(); 01718 return id; 01719 } 01720 01721 int WindowQObject::installTimeout(const Value &func, List args, int t, bool singleShot) 01722 { 01723 Object objFunc = Object::dynamicCast( func ); 01724 if (!objFunc.isValid()) 01725 return 0; 01726 int id = ++lastTimerId; 01727 if (t < 10) t = 10; 01728 QTime nextTime = QTime::currentTime().addMSecs(-pausedTime).addMSecs(t); 01729 ScheduledAction *action = new ScheduledAction(objFunc,args,nextTime,t,singleShot,id); 01730 scheduledActions.append(action); 01731 setNextTimer(); 01732 return id; 01733 } 01734 01735 void WindowQObject::clearTimeout(int timerId) 01736 { 01737 QPtrListIterator<ScheduledAction> it(scheduledActions); 01738 for (; it.current(); ++it) { 01739 ScheduledAction *action = it.current(); 01740 if (action->timerId == timerId) { 01741 scheduledActions.removeRef(action); 01742 if (!action->executing) 01743 delete action; 01744 return; 01745 } 01746 } 01747 } 01748 01749 void WindowQObject::mark() 01750 { 01751 QPtrListIterator<ScheduledAction> it(scheduledActions); 01752 for (; it.current(); ++it) 01753 it.current()->mark(); 01754 } 01755 01756 void WindowQObject::timerEvent(QTimerEvent *) 01757 { 01758 killTimers(); 01759 01760 if (scheduledActions.isEmpty()) 01761 return; 01762 01763 QTime currentActual = QTime::currentTime(); 01764 QTime currentAdjusted = currentActual.addMSecs(-pausedTime); 01765 01766 // Work out which actions are to be executed. We take a separate copy of 01767 // this list since the main one may be modified during action execution 01768 QPtrList<ScheduledAction> toExecute; 01769 QPtrListIterator<ScheduledAction> it(scheduledActions); 01770 for (; it.current(); ++it) 01771 if (currentAdjusted >= it.current()->nextTime) 01772 toExecute.append(it.current()); 01773 01774 // ### verify that the window can't be closed (and action deleted) during execution 01775 it = QPtrListIterator<ScheduledAction>(toExecute); 01776 for (; it.current(); ++it) { 01777 ScheduledAction *action = it.current(); 01778 if (!scheduledActions.containsRef(action)) // removed by clearTimeout() 01779 continue; 01780 01781 action->executing = true; // prevent deletion in clearTimeout() 01782 01783 if (action->singleShot) 01784 scheduledActions.removeRef(action); 01785 if (!parent->part().isNull()) 01786 action->execute(parent); 01787 01788 action->executing = false; 01789 01790 if (!scheduledActions.containsRef(action)) 01791 delete action; 01792 else 01793 action->nextTime = action->nextTime.addMSecs(action->interval); 01794 } 01795 01796 pausedTime += currentActual.msecsTo(QTime::currentTime()); 01797 01798 // Work out when next event is to occur 01799 setNextTimer(); 01800 } 01801 01802 void WindowQObject::setNextTimer() 01803 { 01804 if (scheduledActions.isEmpty()) 01805 return; 01806 01807 QPtrListIterator<ScheduledAction> it(scheduledActions); 01808 QTime nextTime = it.current()->nextTime; 01809 for (++it; it.current(); ++it) 01810 if (nextTime > it.current()->nextTime) 01811 nextTime = it.current()->nextTime; 01812 01813 QTime nextTimeActual = nextTime.addMSecs(pausedTime); 01814 int nextInterval = QTime::currentTime().msecsTo(nextTimeActual); 01815 if (nextInterval < 0) 01816 nextInterval = 0; 01817 startTimer(nextInterval); 01818 } 01819 01820 void WindowQObject::timeoutClose() 01821 { 01822 parent->closeNow(); 01823 } 01824 01825 Value FrameArray::get(ExecState *exec, const Identifier &p) const 01826 { 01827 #ifdef KJS_VERBOSE 01828 kdDebug(6070) << "FrameArray::get " << p.qstring() << " part=" << (void*)part << endl; 01829 #endif 01830 if (part.isNull()) 01831 return Undefined(); 01832 01833 QPtrList<KParts::ReadOnlyPart> frames = part->frames(); 01834 unsigned int len = frames.count(); 01835 if (p == lengthPropertyName) 01836 return Number(len); 01837 else if (p== "location") // non-standard property, but works in NS and IE 01838 { 01839 Object obj = Object::dynamicCast( Window::retrieve( part ) ); 01840 if ( !obj.isNull() ) 01841 return obj.get( exec, "location" ); 01842 return Undefined(); 01843 } 01844 01845 // check for the name or number 01846 KParts::ReadOnlyPart *frame = part->findFrame(p.qstring()); 01847 if (!frame) { 01848 bool ok; 01849 unsigned int i = p.toArrayIndex(&ok); 01850 if (ok && i < len) 01851 frame = frames.at(i); 01852 } 01853 01854 // we are potentially fetching a reference to a another Window object here. 01855 // i.e. we may be accessing objects from another interpreter instance. 01856 // Therefore we have to be a bit careful with memory management. 01857 if (frame && ::qt_cast<KHTMLPart*>(frame)) { 01858 KHTMLPart *khtml = static_cast<KHTMLPart*>(frame); 01859 return Window::retrieve(khtml); 01860 } 01861 01862 return ObjectImp::get(exec, p); 01863 } 01864 01866 01867 const ClassInfo Location::info = { "Location", 0, &LocationTable, 0 }; 01868 /* 01869 @begin LocationTable 11 01870 hash Location::Hash DontDelete 01871 host Location::Host DontDelete 01872 hostname Location::Hostname DontDelete 01873 href Location::Href DontDelete 01874 pathname Location::Pathname DontDelete 01875 port Location::Port DontDelete 01876 protocol Location::Protocol DontDelete 01877 search Location::Search DontDelete 01878 [[==]] Location::EqualEqual DontDelete|ReadOnly 01879 assign Location::Assign DontDelete|Function 1 01880 toString Location::ToString DontDelete|Function 0 01881 replace Location::Replace DontDelete|Function 1 01882 reload Location::Reload DontDelete|Function 0 01883 @end 01884 */ 01885 IMPLEMENT_PROTOFUNC_DOM(LocationFunc) 01886 Location::Location(KHTMLPart *p) : m_part(p) 01887 { 01888 //kdDebug(6070) << "Location::Location " << this << " m_part=" << (void*)m_part << endl; 01889 } 01890 01891 Location::~Location() 01892 { 01893 //kdDebug(6070) << "Location::~Location " << this << " m_part=" << (void*)m_part << endl; 01894 } 01895 01896 Value Location::get(ExecState *exec, const Identifier &p) const 01897 { 01898 #ifdef KJS_VERBOSE 01899 kdDebug(6070) << "Location::get " << p.qstring() << " m_part=" << (void*)m_part << endl; 01900 #endif 01901 01902 if (m_part.isNull()) 01903 return Undefined(); 01904 01905 const HashEntry *entry = Lookup::findEntry(&LocationTable, p); 01906 01907 // properties that work on all Location objects 01908 if ( entry && entry->value == Replace ) 01909 return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr); 01910 01911 // XSS check 01912 const Window* window = Window::retrieveWindow( m_part ); 01913 if ( !window || !window->isSafeScript(exec) ) 01914 return Undefined(); 01915 01916 KURL url = m_part->url(); 01917 if (entry) 01918 switch (entry->value) { 01919 case Hash: 01920 return String( url.ref().isNull() ? QString("") : "#" + url.ref() ); 01921 case Host: { 01922 UString str = url.host(); 01923 if (url.port()) 01924 str += ":" + QString::number((int)url.port()); 01925 return String(str); 01926 // Note: this is the IE spec. The NS spec swaps the two, it says 01927 // "The hostname property is the concatenation of the host and port properties, separated by a colon." 01928 // Bleh. 01929 } 01930 case Hostname: 01931 return String( url.host() ); 01932 case Href: 01933 if (!url.hasPath()) 01934 return String( url.prettyURL()+"/" ); 01935 else 01936 return String( url.prettyURL() ); 01937 case Pathname: 01938 return String( url.path().isEmpty() ? QString("/") : url.path() ); 01939 case Port: 01940 return String( url.port() ? QString::number((int)url.port()) : QString::fromLatin1("") ); 01941 case Protocol: 01942 return String( url.protocol()+":" ); 01943 case Search: 01944 return String( url.query() ); 01945 case EqualEqual: // [[==]] 01946 return String(toString(exec)); 01947 case ToString: 01948 return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr); 01949 } 01950 // Look for overrides 01951 ValueImp * val = ObjectImp::getDirect(p); 01952 if (val) 01953 return Value(val); 01954 if (entry && (entry->attr & Function)) 01955 return lookupOrCreateFunction<LocationFunc>(exec,p,this,entry->value,entry->params,entry->attr); 01956 01957 return Undefined(); 01958 } 01959 01960 void Location::put(ExecState *exec, const Identifier &p, const Value &v, int attr) 01961 { 01962 #ifdef KJS_VERBOSE 01963 kdDebug(6070) << "Location::put " << p.qstring() << " m_part=" << (void*)m_part << endl; 01964 #endif 01965 if (m_part.isNull()) 01966 return; 01967 01968 // XSS check 01969 const Window* window = Window::retrieveWindow( m_part ); 01970 if ( !window || !window->isSafeScript(exec) ) 01971 return; 01972 01973 QString str = v.toString(exec).qstring(); 01974 KURL url = m_part->url(); 01975 const HashEntry *entry = Lookup::findEntry(&LocationTable, p); 01976 if (entry) 01977 switch (entry->value) { 01978 case Href: { 01979 KHTMLPart* p = Window::retrieveActive(exec)->part(); 01980 if ( p ) 01981 url = p->htmlDocument().completeURL( str ).string(); 01982 else 01983 url = str; 01984 break; 01985 } 01986 case Hash: 01987 // when the hash is already the same ignore it 01988 if (str == url.ref()) return; 01989 url.setRef(str); 01990 break; 01991 case Host: { 01992 QString host = str.left(str.find(":")); 01993 QString port = str.mid(str.find(":")+1); 01994 url.setHost(host); 01995 url.setPort(port.toUInt()); 01996 break; 01997 } 01998 case Hostname: 01999 url.setHost(str); 02000 break; 02001 case Pathname: 02002 url.setPath(str); 02003 break; 02004 case Port: 02005 url.setPort(str.toUInt()); 02006 break; 02007 case Protocol: 02008 url.setProtocol(str); 02009 break; 02010 case Search: 02011 url.setQuery(str); 02012 break; 02013 } 02014 else { 02015 ObjectImp::put(exec, p, v, attr); 02016 return; 02017 } 02018 02019 Window::retrieveWindow(m_part)->goURL(exec, url.url(), false /* don't lock history*/ ); 02020 } 02021 02022 Value Location::toPrimitive(ExecState *exec, Type) const 02023 { 02024 Window* window = Window::retrieveWindow( m_part ); 02025 if ( window && window->isSafeScript(exec) ) 02026 return String(toString(exec)); 02027 return Undefined(); 02028 } 02029 02030 UString Location::toString(ExecState *exec) const 02031 { 02032 Window* window = Window::retrieveWindow( m_part ); 02033 if ( window && window->isSafeScript(exec) ) 02034 { 02035 if (!m_part->url().hasPath()) 02036 return m_part->url().prettyURL()+"/"; 02037 else 02038 return m_part->url().prettyURL(); 02039 } 02040 return ""; 02041 } 02042 02043 Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) 02044 { 02045 KJS_CHECK_THIS( Location, thisObj ); 02046 Location *location = static_cast<Location *>(thisObj.imp()); 02047 KHTMLPart *part = location->part(); 02048 02049 if (!part) return Undefined(); 02050 02051 Window* window = Window::retrieveWindow(part); 02052 02053 if ( !window->isSafeScript(exec) && id != Location::Replace) 02054 return Undefined(); 02055 02056 switch (id) { 02057 case Location::Assign: 02058 case Location::Replace: 02059 Window::retrieveWindow(part)->goURL(exec, args[0].toString(exec).qstring(), 02060 id == Location::Replace); 02061 break; 02062 case Location::Reload: 02063 part->scheduleRedirection(-1, part->url().url(), true/*lock history*/); 02064 break; 02065 case Location::ToString: 02066 return String(location->toString(exec)); 02067 } 02068 return Undefined(); 02069 } 02070 02072 02073 const ClassInfo External::info = { "External", 0, 0, 0 }; 02074 /* 02075 @begin ExternalTable 4 02076 addFavorite External::AddFavorite DontDelete|Function 1 02077 @end 02078 */ 02079 IMPLEMENT_PROTOFUNC_DOM(ExternalFunc) 02080 02081 Value External::get(ExecState *exec, const Identifier &p) const 02082 { 02083 return lookupGetFunction<ExternalFunc,ObjectImp>(exec,p,&ExternalTable,this); 02084 } 02085 02086 Value ExternalFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) 02087 { 02088 KJS_CHECK_THIS( External, thisObj ); 02089 External *external = static_cast<External *>(thisObj.imp()); 02090 02091 KHTMLPart *part = external->part; 02092 if (!part) 02093 return Undefined(); 02094 02095 KHTMLView *widget = part->view(); 02096 02097 switch (id) { 02098 case External::AddFavorite: 02099 { 02100 if (!widget->dialogsAllowed()) 02101 return Undefined(); 02102 part->xmlDocImpl()->updateRendering(); 02103 if (args.size() != 1 && args.size() != 2) 02104 return Undefined(); 02105 02106 QString url = args[0].toString(exec).qstring(); 02107 QString title; 02108 if (args.size() == 2) 02109 title = args[1].toString(exec).qstring(); 02110 02111 // AK - don't do anything yet, for the moment i 02112 // just wanted the base js handling code in cvs 02113 return Undefined(); 02114 02115 QString question; 02116 if ( title.isEmpty() ) 02117 question = i18n("Do you want a bookmark pointing to the location \"%1\" to be added to your collection?") 02118 .arg(url); 02119 else 02120 question = i18n("Do you want a bookmark pointing to the location \"%1\" titled \"%2\" to be added to your collection?") 02121 .arg(url).arg(title); 02122 02123 if (KMessageBox::warningYesNo( 02124 widget, question, 02125 i18n("JavaScript Attempted Bookmark Insert"), 02126 i18n("Insert"), i18n("Disallow")) == KMessageBox::Yes) 02127 { 02128 KBookmarkManager *mgr = KBookmarkManager::userBookmarksManager(); 02129 mgr->addBookmarkDialog(url,title); 02130 } 02131 break; 02132 } 02133 default: 02134 return Undefined(); 02135 } 02136 02137 return Undefined(); 02138 } 02139 02141 02142 const ClassInfo History::info = { "History", 0, 0, 0 }; 02143 /* 02144 @begin HistoryTable 4 02145 length History::Length DontDelete|ReadOnly 02146 back History::Back DontDelete|Function 0 02147 forward History::Forward DontDelete|Function 0 02148 go History::Go DontDelete|Function 1 02149 @end 02150 */ 02151 IMPLEMENT_PROTOFUNC_DOM(HistoryFunc) 02152 02153 Value History::get(ExecState *exec, const Identifier &p) const 02154 { 02155 return lookupGet<HistoryFunc,History,ObjectImp>(exec,p,&HistoryTable,this); 02156 } 02157 02158 Value History::getValueProperty(ExecState *, int token) const 02159 { 02160 // if previous or next is implemented, make sure its not a major 02161 // privacy leak (see i.e. http://security.greymagic.com/adv/gm005-op/) 02162 switch (token) { 02163 case Length: 02164 { 02165 KParts::BrowserExtension *ext = part->browserExtension(); 02166 if ( !ext ) 02167 return Number( 0 ); 02168 02169 KParts::BrowserInterface *iface = ext->browserInterface(); 02170 if ( !iface ) 02171 return Number( 0 ); 02172 02173 QVariant length = iface->property( "historyLength" ); 02174 02175 if ( length.type() != QVariant::UInt ) 02176 return Number( 0 ); 02177 02178 return Number( length.toUInt() ); 02179 } 02180 default: 02181 kdDebug(6070) << "WARNING: Unhandled token in History::getValueProperty : " << token << endl; 02182 return Undefined(); 02183 } 02184 } 02185 02186 Value HistoryFunc::tryCall(ExecState *exec, Object &thisObj, const List &args) 02187 { 02188 KJS_CHECK_THIS( History, thisObj ); 02189 History *history = static_cast<History *>(thisObj.imp()); 02190 02191 Value v = args[0]; 02192 Number n; 02193 if(!v.isNull()) 02194 n = v.toInteger(exec); 02195 02196 int steps; 02197 switch (id) { 02198 case History::Back: 02199 steps = -1; 02200 break; 02201 case History::Forward: 02202 steps = 1; 02203 break; 02204 case History::Go: 02205 steps = n.intValue(); 02206 break; 02207 default: 02208 return Undefined(); 02209 } 02210 02211 // Special case for go(0) from a frame -> reload only the frame 02212 // go(i!=0) from a frame navigates into the history of the frame only, 02213 // in both IE and NS (but not in Mozilla).... we can't easily do that 02214 // in Konqueror... 02215 if (!steps) // add && history->part->parentPart() to get only frames, but doesn't matter 02216 { 02217 history->part->openURL( history->part->url() ); 02218 } else 02219 { 02220 // Delay it. 02221 // Testcase: history.back(); alert("hello"); 02222 Window* window = Window::retrieveWindow( history->part ); 02223 window->delayedGoHistory( steps ); 02224 } 02225 return Undefined(); 02226 } 02227 02229 02230 #ifdef Q_WS_QWS 02231 02232 const ClassInfo Konqueror::info = { "Konqueror", 0, 0, 0 }; 02233 02234 bool Konqueror::hasProperty(ExecState *exec, const Identifier &p) const 02235 { 02236 if ( p.qstring().startsWith( "goHistory" ) ) return false; 02237 02238 return true; 02239 } 02240 02241 Value Konqueror::get(ExecState *exec, const Identifier &p) const 02242 { 02243 if ( p == "goHistory" || part->url().protocol() != "http" || part->url().host() != "localhost" ) 02244 return Undefined(); 02245 02246 KParts::BrowserExtension *ext = part->browserExtension(); 02247 if ( ext ) { 02248 KParts::BrowserInterface *iface = ext->browserInterface(); 02249 if ( iface ) { 02250 QVariant prop = iface->property( p.qstring().latin1() ); 02251 02252 if ( prop.isValid() ) { 02253 switch( prop.type() ) { 02254 case QVariant::Int: 02255 return Number( prop.toInt() ); 02256 case QVariant::String: 02257 return String( prop.toString() ); 02258 default: 02259 break; 02260 } 02261 } 02262 } 02263 } 02264 02265 return Value( new KonquerorFunc(this, p.qstring().latin1() ) ); 02266 } 02267 02268 Value KonquerorFunc::tryCall(ExecState *exec, Object &, const List &args) 02269 { 02270 KParts::BrowserExtension *ext = konqueror->part->browserExtension(); 02271 02272 if(!ext) 02273 return Undefined(); 02274 02275 KParts::BrowserInterface *iface = ext->browserInterface(); 02276 02277 if ( !iface ) 02278 return Undefined(); 02279 02280 QCString n = m_name.data(); 02281 n += "()"; 02282 iface->callMethod( n.data(), QVariant() ); 02283 02284 return Undefined(); 02285 } 02286 02287 UString Konqueror::toString(ExecState *) const 02288 { 02289 return UString("[object Konqueror]"); 02290 } 02291 02292 #endif 02293 02294 02295 #include "kjs_window.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:50:31 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003