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