Changeset 28794 in webkit
- Timestamp:
- Dec 16, 2007 8:50:53 PM (16 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 9 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r28792 r28794 1 2007-12-16 Sam Weinig <sam@webkit.org> 2 3 Reviewed by Maciej. 4 5 Yet more of http://bugs.webkit.org/show_bug.cgi?id=16385 6 Cleanup kjs_window 7 8 - Move ScheduledAction into its own file and put it in the WebCore namespace. 9 10 * WebCore.pro: 11 * WebCore.vcproj/WebCore.vcproj: 12 * WebCore.xcodeproj/project.pbxproj: 13 * WebCoreSources.bkl: 14 * bindings/js/PausedTimeouts.cpp: 15 * bindings/js/PausedTimeouts.h: 16 * bindings/js/ScheduledAction.cpp: Copied from bindings/js/kjs_window.cpp. 17 (WebCore::ScheduledAction::ScheduledAction): 18 (WebCore::ScheduledAction::execute): 19 * bindings/js/ScheduledAction.h: Copied from bindings/js/kjs_window.h. 20 (WebCore::ScheduledAction::ScheduledAction): 21 * bindings/js/kjs_window.cpp: 22 (KJS::DOMWindowTimer::DOMWindowTimer): 23 (KJS::DOMWindowTimer::action): 24 (KJS::DOMWindowTimer::takeAction): 25 (KJS::Window::installTimeout): 26 (KJS::Window::timerFired): 27 * bindings/js/kjs_window.h: 28 1 29 2007-12-16 Alp Toker <alp@atoker.com> 2 30 -
trunk/WebCore/WebCore.pro
r28792 r28794 420 420 bindings/js/kjs_window.cpp \ 421 421 bindings/js/PausedTimeouts.cpp \ 422 bindings/js/ScheduledAction.cpp \ 422 423 css/CSSBorderImageValue.cpp \ 423 424 css/CSSCharsetRule.cpp \ -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r28790 r28794 7648 7648 > 7649 7649 </File> 7650 <File 7651 RelativePath="..\bindings\js\ScheduledAction.cpp" 7652 > 7653 </File> 7654 <File 7655 RelativePath="..\bindings\js\ScheduledAction.h" 7656 > 7657 </File> 7650 7658 </Filter> 7651 7659 </Filter> -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r28791 r28794 3644 3644 BCA378160D15C64600B793D6 /* PausedTimeouts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */; }; 3645 3645 BCA378170D15C64600B793D6 /* PausedTimeouts.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA378150D15C64600B793D6 /* PausedTimeouts.h */; }; 3646 BCA378BC0D15F64200B793D6 /* ScheduledAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */; }; 3647 BCA378BD0D15F64200B793D6 /* ScheduledAction.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA378BB0D15F64200B793D6 /* ScheduledAction.h */; }; 3646 3648 BCA85A100C3AEAF4006F8308 /* DOMSVGNumberInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */; }; 3647 3649 BCAA90C30A7EBA60008B1229 /* ScrollBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */; }; … … 7655 7657 BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PausedTimeouts.cpp; sourceTree = "<group>"; }; 7656 7658 BCA378150D15C64600B793D6 /* PausedTimeouts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PausedTimeouts.h; sourceTree = "<group>"; }; 7659 BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScheduledAction.cpp; sourceTree = "<group>"; }; 7660 BCA378BB0D15F64200B793D6 /* ScheduledAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScheduledAction.h; sourceTree = "<group>"; }; 7657 7661 BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMSVGNumberInternal.h; sourceTree = "<group>"; }; 7658 7662 BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScrollBar.cpp; path = platform/ScrollBar.cpp; sourceTree = SOURCE_ROOT; }; … … 11410 11414 BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */, 11411 11415 BCA378150D15C64600B793D6 /* PausedTimeouts.h */, 11416 BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */, 11417 BCA378BB0D15F64200B793D6 /* ScheduledAction.h */, 11412 11418 ); 11413 11419 path = js; … … 14107 14113 B28BC31A0D135E5400CDBA27 /* JSEventTargetBase.lut.h in Headers */, 14108 14114 BCA378170D15C64600B793D6 /* PausedTimeouts.h in Headers */, 14115 BCA378BD0D15F64200B793D6 /* ScheduledAction.h in Headers */, 14109 14116 ); 14110 14117 runOnlyForDeploymentPostprocessing = 0; … … 15819 15826 BC4BF9E40D11E133007D247F /* ClassNames.cpp in Sources */, 15820 15827 BCA378160D15C64600B793D6 /* PausedTimeouts.cpp in Sources */, 15828 BCA378BC0D15F64200B793D6 /* ScheduledAction.cpp in Sources */, 15821 15829 ); 15822 15830 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/WebCoreSources.bkl
r28779 r28794 94 94 bindings/js/kjs_window.cpp 95 95 bindings/js/PausedTimeouts.cpp 96 bindings/js/ScheduledAction.cpp 96 97 </set> 97 98 -
trunk/WebCore/bindings/js/PausedTimeouts.cpp
r28779 r28794 24 24 #include "PausedTimeouts.h" 25 25 26 #include " kjs_window.h"26 #include "ScheduledAction.h" 27 27 28 28 namespace WebCore { -
trunk/WebCore/bindings/js/PausedTimeouts.h
r28779 r28794 23 23 #include <wtf/Noncopyable.h> 24 24 25 namespace KJS { 25 namespace WebCore { 26 26 27 class ScheduledAction; 27 }28 29 namespace WebCore {30 28 31 29 struct PausedTimeout { … … 34 32 double nextFireInterval; 35 33 double repeatInterval; 36 KJS::ScheduledAction* action;34 ScheduledAction* action; 37 35 }; 38 36 -
trunk/WebCore/bindings/js/ScheduledAction.cpp
r28779 r28794 1 // -*- c-basic-offset: 4 -*-2 1 /* 3 2 * Copyright (C) 2000 Harri Porten (porten@kde.org) … … 23 22 24 23 #include "config.h" 25 #include " kjs_window.h"24 #include "ScheduledAction.h" 26 25 27 #include "Base64.h"28 26 #include "CString.h" 29 27 #include "Chrome.h" 30 28 #include "DOMWindow.h" 31 #include "Element.h" 32 #include "EventListener.h" 33 #include "EventNames.h" 34 #include "ExceptionCode.h" 35 #include "FloatRect.h" 29 #include "Document.h" 36 30 #include "Frame.h" 37 #include "FrameLoadRequest.h"38 31 #include "FrameLoader.h" 39 #include "FrameTree.h"40 #include "GCController.h"41 #include "HTMLDocument.h"42 #include "JSDOMExceptionConstructor.h"43 #include "JSDOMWindow.h"44 #include "JSEvent.h"45 #include "JSHTMLAudioElementConstructor.h"46 #include "JSHTMLCollection.h"47 #include "JSHTMLOptionElementConstructor.h"48 #include "JSXMLHttpRequest.h"49 #include "Logging.h"50 32 #include "Page.h" 51 #include "PausedTimeouts.h"52 #include "PlatformScreen.h"53 #include "PlugInInfoStore.h"54 #include "RenderView.h"55 #include "SecurityOrigin.h"56 #include "Settings.h"57 #include "WindowFeatures.h"58 #include "htmlediting.h"59 #include "kjs_css.h"60 #include "kjs_events.h"61 #include "kjs_navigator.h"62 33 #include "kjs_proxy.h" 63 #include <wtf/MathExtras.h>34 #include "kjs_window.h" 64 35 65 #if ENABLE(XSLT) 66 #include "JSXSLTProcessor.h" 67 #endif 36 using namespace KJS; 68 37 69 using namespace WebCore; 70 using namespace EventNames; 38 namespace WebCore { 71 39 72 namespace KJS { 73 74 static int lastUsedTimeoutId; 75 76 static int timerNestingLevel = 0; 77 const int cMaxTimerNestingLevel = 5; 78 const double cMinimumTimerInterval = 0.010; 79 80 struct WindowPrivate { 81 WindowPrivate() 82 : loc(0) 83 , m_evt(0) 84 , m_returnValueSlot(0) 85 { 86 } 87 88 Window::ListenersMap jsEventListeners; 89 Window::ListenersMap jsHTMLEventListeners; 90 Window::UnprotectedListenersMap jsUnprotectedEventListeners; 91 Window::UnprotectedListenersMap jsUnprotectedHTMLEventListeners; 92 mutable Location* loc; 93 WebCore::Event* m_evt; 94 JSValue** m_returnValueSlot; 95 96 typedef HashMap<int, DOMWindowTimer*> TimeoutsMap; 97 TimeoutsMap m_timeouts; 98 }; 99 100 class DOMWindowTimer : public TimerBase { 101 public: 102 DOMWindowTimer(int timeoutId, int nestingLevel, Window* object, ScheduledAction* action) 103 : m_timeoutId(timeoutId) 104 , m_nestingLevel(nestingLevel) 105 , m_object(object) 106 , m_action(action) 107 { 108 } 109 110 virtual ~DOMWindowTimer() 111 { 112 JSLock lock; 113 delete m_action; 114 } 115 116 int timeoutId() const { return m_timeoutId; } 117 118 int nestingLevel() const { return m_nestingLevel; } 119 void setNestingLevel(int n) { m_nestingLevel = n; } 120 121 ScheduledAction* action() const { return m_action; } 122 ScheduledAction* takeAction() { ScheduledAction* a = m_action; m_action = 0; return a; } 123 124 private: 125 virtual void fired(); 126 127 int m_timeoutId; 128 int m_nestingLevel; 129 Window* m_object; 130 ScheduledAction* m_action; 131 }; 132 133 } // namespace KJS 134 135 #include "kjs_window.lut.h" 136 137 namespace KJS { 138 139 ////////////////////// Window Object //////////////////////// 140 141 const ClassInfo Window::info = { "Window", 0, &WindowTable }; 142 143 /* 144 @begin WindowTable 118 145 # Warning, when adding a function to this object you need to add a case in Window::get 146 # -- Functions -- 147 atob &WindowProtoFuncAToB::create DontDelete|Function 1 148 btoa &WindowProtoFuncBToA::create DontDelete|Function 1 149 open &WindowProtoFuncOpen::create DontDelete|Function 3 150 setTimeout &WindowProtoFuncSetTimeout::create DontDelete|Function 2 151 clearTimeout &WindowProtoFuncClearTimeout::create DontDelete|Function 1 152 setInterval &WindowProtoFuncSetInterval::create DontDelete|Function 2 153 clearInterval &WindowProtoFuncClearTimeout::create DontDelete|Function 1 154 addEventListener &WindowProtoFuncAddEventListener::create DontDelete|Function 3 155 removeEventListener &WindowProtoFuncRemoveEventListener::create DontDelete|Function 3 156 showModalDialog &WindowProtoFuncShowModalDialog::create DontDelete|Function 1 157 # Not implemented 158 captureEvents &WindowProtoFuncNotImplemented::create DontDelete|Function 0 159 releaseEvents &WindowProtoFuncNotImplemented::create DontDelete|Function 0 160 161 # -- Attributes -- 162 crypto Window::Crypto DontDelete|ReadOnly 163 event Window::Event_ DontDelete 164 location Window::Location_ DontDelete 165 navigator Window::Navigator_ DontDelete|ReadOnly 166 clientInformation Window::ClientInformation DontDelete|ReadOnly 167 # -- Event Listeners -- 168 onabort Window::Onabort DontDelete 169 onblur Window::Onblur DontDelete 170 onchange Window::Onchange DontDelete 171 onclick Window::Onclick DontDelete 172 ondblclick Window::Ondblclick DontDelete 173 onerror Window::Onerror DontDelete 174 onfocus Window::Onfocus DontDelete 175 onkeydown Window::Onkeydown DontDelete 176 onkeypress Window::Onkeypress DontDelete 177 onkeyup Window::Onkeyup DontDelete 178 onload Window::Onload DontDelete 179 onmousedown Window::Onmousedown DontDelete 180 onmousemove Window::Onmousemove DontDelete 181 onmouseout Window::Onmouseout DontDelete 182 onmouseover Window::Onmouseover DontDelete 183 onmouseup Window::Onmouseup DontDelete 184 onmousewheel Window::OnWindowMouseWheel DontDelete 185 onreset Window::Onreset DontDelete 186 onresize Window::Onresize DontDelete 187 onscroll Window::Onscroll DontDelete 188 onsearch Window::Onsearch DontDelete 189 onselect Window::Onselect DontDelete 190 onsubmit Window::Onsubmit DontDelete 191 onunload Window::Onunload DontDelete 192 onbeforeunload Window::Onbeforeunload DontDelete 193 # -- Constructors -- 194 Audio Window::Audio DontDelete 195 DOMException Window::DOMException DontDelete 196 Image Window::Image DontDelete 197 Option Window::Option DontDelete 198 XMLHttpRequest Window::XMLHttpRequest DontDelete 199 XSLTProcessor Window::XSLTProcessor_ DontDelete 200 @end 201 */ 202 203 Window::Window(DOMWindow* window) 204 : m_impl(window) 205 , d(new WindowPrivate) 40 ScheduledAction::ScheduledAction(JSValue* func, const List& args) 41 : m_func(func) 206 42 { 207 // Window destruction is not thread-safe because of 208 // the non-thread-safe WebCore structures it references. 209 Collector::collectOnMainThreadOnly(this); 210 211 // Time in milliseconds before the script timeout handler kicks in. 212 setTimeoutTime(10000); 43 List::const_iterator end = args.end(); 44 for (List::const_iterator it = args.begin(); it != end; ++it) 45 m_args.append(*it); 213 46 } 214 47 215 Window::~Window()216 {217 clearAllTimeouts();218 219 // Clear any backpointers to the window220 221 ListenersMap::iterator i2 = d->jsEventListeners.begin();222 ListenersMap::iterator e2 = d->jsEventListeners.end();223 for (; i2 != e2; ++i2)224 i2->second->clearWindowObj();225 i2 = d->jsHTMLEventListeners.begin();226 e2 = d->jsHTMLEventListeners.end();227 for (; i2 != e2; ++i2)228 i2->second->clearWindowObj();229 230 UnprotectedListenersMap::iterator i1 = d->jsUnprotectedEventListeners.begin();231 UnprotectedListenersMap::iterator e1 = d->jsUnprotectedEventListeners.end();232 for (; i1 != e1; ++i1)233 i1->second->clearWindowObj();234 i1 = d->jsUnprotectedHTMLEventListeners.begin();235 e1 = d->jsUnprotectedHTMLEventListeners.end();236 for (; i1 != e1; ++i1)237 i1->second->clearWindowObj();238 }239 240 Window* Window::retrieveWindow(Frame* frame)241 {242 JSObject* o = retrieve(frame)->getObject();243 244 ASSERT(o || !frame->settings() || !frame->settings()->isJavaScriptEnabled());245 return static_cast<Window*>(o);246 }247 248 Window* Window::retrieveActive(ExecState* exec)249 {250 JSGlobalObject* globalObject = exec->dynamicGlobalObject();251 ASSERT(globalObject);252 return static_cast<Window*>(globalObject);253 }254 255 JSValue* Window::retrieve(Frame* frame)256 {257 ASSERT(frame);258 if (KJSProxy* proxy = frame->scriptProxy())259 return proxy->globalObject(); // the Global object is the "window"260 261 return jsUndefined(); // This can happen with JS disabled on the domain of that window262 }263 264 Location* Window::location() const265 {266 if (!d->loc)267 d->loc = new Location(impl()->frame());268 return d->loc;269 }270 271 // reference our special objects during garbage collection272 void Window::mark()273 {274 JSGlobalObject::mark();275 if (d->loc && !d->loc->marked())276 d->loc->mark();277 }278 279 static bool allowPopUp(Frame* frame)280 {281 if (!frame)282 return false;283 if (frame->scriptProxy()->processingUserGesture())284 return true;285 Settings* settings = frame->settings();286 return settings && settings->JavaScriptCanOpenWindowsAutomatically();287 }288 289 static HashMap<String, String> parseModalDialogFeatures(const String& featuresArg)290 {291 HashMap<String, String> map;292 293 Vector<String> features = featuresArg.split(';');294 Vector<String>::const_iterator end = features.end();295 for (Vector<String>::const_iterator it = features.begin(); it != end; ++it) {296 String s = *it;297 int pos = s.find('=');298 int colonPos = s.find(':');299 if (pos >= 0 && colonPos >= 0)300 continue; // ignore any strings that have both = and :301 if (pos < 0)302 pos = colonPos;303 if (pos < 0) {304 // null string for value means key without value305 map.set(s.stripWhiteSpace().lower(), String());306 } else {307 String key = s.left(pos).stripWhiteSpace().lower();308 String val = s.substring(pos + 1).stripWhiteSpace().lower();309 int spacePos = val.find(' ');310 if (spacePos != -1)311 val = val.left(spacePos);312 map.set(key, val);313 }314 }315 316 return map;317 }318 319 static Frame* createWindow(ExecState* exec, Frame* openerFrame, const String& url,320 const String& frameName, const WindowFeatures& windowFeatures, JSValue* dialogArgs)321 {322 Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();323 324 ResourceRequest request;325 if (activeFrame)326 request.setHTTPReferrer(activeFrame->loader()->outgoingReferrer());327 FrameLoadRequest frameRequest(request, frameName);328 329 // FIXME: It's much better for client API if a new window starts with a URL, here where we330 // know what URL we are going to open. Unfortunately, this code passes the empty string331 // for the URL, but there's a reason for that. Before loading we have to set up the opener,332 // openedByDOM, and dialogArguments values. Also, to decide whether to use the URL we currently333 // do an allowsAccessFrom call using the window we create, which can't be done before creating it.334 // We'd have to resolve all those issues to pass the URL instead of "".335 336 bool created;337 Frame* newFrame = openerFrame->loader()->createWindow(frameRequest, windowFeatures, created);338 if (!newFrame)339 return 0;340 341 newFrame->loader()->setOpener(openerFrame);342 newFrame->loader()->setOpenedByDOM();343 344 Window* newWindow = Window::retrieveWindow(newFrame);345 346 if (dialogArgs)347 newWindow->putDirect("dialogArguments", dialogArgs);348 349 if (!url.startsWith("javascript:", false) || newWindow->allowsAccessFrom(exec)) {350 String completedURL = url.isEmpty() ? url : activeFrame->document()->completeURL(url);351 bool userGesture = activeFrame->scriptProxy()->processingUserGesture();352 353 if (created) {354 newFrame->loader()->changeLocation(KURL(completedURL.deprecatedString()), activeFrame->loader()->outgoingReferrer(), false, userGesture);355 if (Document* oldDoc = openerFrame->document()) {356 newFrame->document()->setDomainInternal(oldDoc->domain());357 newFrame->document()->setBaseURL(oldDoc->baseURL());358 }359 } else if (!url.isEmpty())360 newFrame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);361 }362 363 return newFrame;364 }365 366 static bool canShowModalDialog(const Frame* frame)367 {368 if (!frame)369 return false;370 return frame->page()->chrome()->canRunModal();371 }372 373 static bool canShowModalDialogNow(const Frame* frame)374 {375 if (!frame)376 return false;377 return frame->page()->chrome()->canRunModalNow();378 }379 380 static JSValue* showModalDialog(ExecState* exec, Frame* frame, const String& url, JSValue* dialogArgs, const String& featureArgs)381 {382 if (!canShowModalDialogNow(frame) || !allowPopUp(frame))383 return jsUndefined();384 385 const HashMap<String, String> features = parseModalDialogFeatures(featureArgs);386 387 const bool trusted = false;388 389 // The following features from Microsoft's documentation are not implemented:390 // - default font settings391 // - width, height, left, and top specified in units other than "px"392 // - edge (sunken or raised, default is raised)393 // - dialogHide: trusted && boolFeature(features, "dialoghide"), makes dialog hide when you print394 // - help: boolFeature(features, "help", true), makes help icon appear in dialog (what does it do on Windows?)395 // - unadorned: trusted && boolFeature(features, "unadorned");396 397 if (!frame)398 return jsUndefined();399 400 FloatRect screenRect = screenAvailableRect(frame->view());401 402 WindowFeatures wargs;403 wargs.width = WindowFeatures::floatFeature(features, "dialogwidth", 100, screenRect.width(), 620); // default here came from frame size of dialog in MacIE404 wargs.widthSet = true;405 wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE406 wargs.heightSet = true;407 408 wargs.x = WindowFeatures::floatFeature(features, "dialogleft", screenRect.x(), screenRect.right() - wargs.width, -1);409 wargs.xSet = wargs.x > 0;410 wargs.y = WindowFeatures::floatFeature(features, "dialogtop", screenRect.y(), screenRect.bottom() - wargs.height, -1);411 wargs.ySet = wargs.y > 0;412 413 if (WindowFeatures::boolFeature(features, "center", true)) {414 if (!wargs.xSet) {415 wargs.x = screenRect.x() + (screenRect.width() - wargs.width) / 2;416 wargs.xSet = true;417 }418 if (!wargs.ySet) {419 wargs.y = screenRect.y() + (screenRect.height() - wargs.height) / 2;420 wargs.ySet = true;421 }422 }423 424 wargs.dialog = true;425 wargs.resizable = WindowFeatures::boolFeature(features, "resizable");426 wargs.scrollbarsVisible = WindowFeatures::boolFeature(features, "scroll", true);427 wargs.statusBarVisible = WindowFeatures::boolFeature(features, "status", !trusted);428 wargs.menuBarVisible = false;429 wargs.toolBarVisible = false;430 wargs.locationBarVisible = false;431 wargs.fullscreen = false;432 433 Frame* dialogFrame = createWindow(exec, frame, url, "", wargs, dialogArgs);434 if (!dialogFrame)435 return jsUndefined();436 437 Window* dialogWindow = Window::retrieveWindow(dialogFrame);438 439 // Get the return value either just before clearing the dialog window's440 // properties (in Window::clear), or when on return from runModal.441 JSValue* returnValue = 0;442 dialogWindow->setReturnValueSlot(&returnValue);443 dialogFrame->page()->chrome()->runModal();444 dialogWindow->setReturnValueSlot(0);445 446 // If we don't have a return value, get it now.447 // Either Window::clear was not called yet, or there was no return value,448 // and in that case, there's no harm in trying again (no benefit either).449 if (!returnValue)450 returnValue = dialogWindow->getDirect("returnValue");451 452 return returnValue ? returnValue : jsUndefined();453 }454 455 JSValue *Window::getValueProperty(ExecState *exec, int token) const456 {457 ASSERT(impl()->frame());458 459 switch (token) {460 case Crypto:461 return jsUndefined(); // FIXME: implement this462 case DOMException:463 if (!allowsAccessFrom(exec))464 return jsUndefined();465 return getDOMExceptionConstructor(exec);466 case Event_:467 if (!allowsAccessFrom(exec))468 return jsUndefined();469 if (!d->m_evt)470 return jsUndefined();471 return toJS(exec, d->m_evt);472 case Location_:473 return location();474 case Navigator_:475 case ClientInformation: {476 if (!allowsAccessFrom(exec))477 return jsUndefined();478 // Store the navigator in the object so we get the same one each time.479 Navigator *n = new Navigator(exec, impl()->frame());480 // FIXME: this will make the "navigator" object accessible from windows that fail481 // the security check the first time, but not subsequent times, seems weird.482 const_cast<Window *>(this)->putDirect("navigator", n, DontDelete|ReadOnly);483 const_cast<Window *>(this)->putDirect("clientInformation", n, DontDelete|ReadOnly);484 return n;485 }486 case Image:487 if (!allowsAccessFrom(exec))488 return jsUndefined();489 // FIXME: this property (and the few below) probably shouldn't create a new object every490 // time491 return new ImageConstructorImp(exec, impl()->frame()->document());492 case Option:493 if (!allowsAccessFrom(exec))494 return jsUndefined();495 return new JSHTMLOptionElementConstructor(exec, impl()->frame()->document());496 case XMLHttpRequest:497 if (!allowsAccessFrom(exec))498 return jsUndefined();499 return new JSXMLHttpRequestConstructorImp(exec, impl()->frame()->document());500 case Audio:501 #if ENABLE(VIDEO)502 return new JSHTMLAudioElementConstructor(exec, impl()->frame()->document());503 #else504 return jsUndefined();505 #endif506 #if ENABLE(XSLT)507 case XSLTProcessor_:508 if (!allowsAccessFrom(exec))509 return jsUndefined();510 return new XSLTProcessorConstructorImp(exec);511 #else512 case XSLTProcessor_:513 return jsUndefined();514 #endif515 }516 517 if (!allowsAccessFrom(exec))518 return jsUndefined();519 520 switch (token) {521 case Onabort:522 return getListener(exec, abortEvent);523 case Onblur:524 return getListener(exec, blurEvent);525 case Onchange:526 return getListener(exec, changeEvent);527 case Onclick:528 return getListener(exec, clickEvent);529 case Ondblclick:530 return getListener(exec, dblclickEvent);531 case Onerror:532 return getListener(exec, errorEvent);533 case Onfocus:534 return getListener(exec, focusEvent);535 case Onkeydown:536 return getListener(exec, keydownEvent);537 case Onkeypress:538 return getListener(exec, keypressEvent);539 case Onkeyup:540 return getListener(exec, keyupEvent);541 case Onload:542 return getListener(exec, loadEvent);543 case Onmousedown:544 return getListener(exec, mousedownEvent);545 case Onmousemove:546 return getListener(exec, mousemoveEvent);547 case Onmouseout:548 return getListener(exec, mouseoutEvent);549 case Onmouseover:550 return getListener(exec, mouseoverEvent);551 case Onmouseup:552 return getListener(exec, mouseupEvent);553 case OnWindowMouseWheel:554 return getListener(exec, mousewheelEvent);555 case Onreset:556 return getListener(exec, resetEvent);557 case Onresize:558 return getListener(exec,resizeEvent);559 case Onscroll:560 return getListener(exec,scrollEvent);561 case Onsearch:562 return getListener(exec,searchEvent);563 case Onselect:564 return getListener(exec,selectEvent);565 case Onsubmit:566 return getListener(exec,submitEvent);567 case Onbeforeunload:568 return getListener(exec, beforeunloadEvent);569 case Onunload:570 return getListener(exec, unloadEvent);571 }572 ASSERT_NOT_REACHED();573 return jsUndefined();574 }575 576 JSValue* Window::childFrameGetter(ExecState*, JSObject*, const Identifier& propertyName, const PropertySlot& slot)577 {578 return retrieve(static_cast<Window*>(slot.slotBase())->impl()->frame()->tree()->child(AtomicString(propertyName)));579 }580 581 JSValue* Window::indexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot& slot)582 {583 return retrieve(static_cast<Window*>(slot.slotBase())->impl()->frame()->tree()->child(slot.index()));584 }585 586 JSValue *Window::namedItemGetter(ExecState *exec, JSObject *originalObject, const Identifier& propertyName, const PropertySlot& slot)587 {588 Window *thisObj = static_cast<Window *>(slot.slotBase());589 Document *doc = thisObj->impl()->frame()->document();590 ASSERT(thisObj->allowsAccessFrom(exec) && doc && doc->isHTMLDocument());591 592 String name = propertyName;593 RefPtr<WebCore::HTMLCollection> collection = doc->windowNamedItems(name);594 if (collection->length() == 1)595 return toJS(exec, collection->firstItem());596 return toJS(exec, collection.get());597 }598 599 bool Window::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)600 {601 // Check for child frames by name before built-in properties to602 // match Mozilla. This does not match IE, but some sites end up603 // naming frames things that conflict with window properties that604 // are in Moz but not IE. Since we have some of these, we have to do605 // it the Moz way.606 if (impl()->frame()->tree()->child(propertyName)) {607 slot.setCustom(this, childFrameGetter);608 return true;609 }610 611 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);612 if (entry) {613 if (entry->attr & Function) {614 if (entry->value.functionValue == &WindowProtoFuncShowModalDialog::create) {615 if (!canShowModalDialog(impl()->frame()))616 return false;617 }618 if (allowsAccessFrom(exec))619 slot.setStaticEntry(this, entry, staticFunctionGetter);620 else621 slot.setUndefined(this);622 } else623 slot.setStaticEntry(this, entry, staticValueGetter<Window>);624 return true;625 }626 627 // FIXME: Search the whole frame hierachy somewhere around here.628 // We need to test the correct priority order.629 630 // allow window[1] or parent[1] etc. (#56983)631 bool ok;632 unsigned i = propertyName.toArrayIndex(&ok);633 if (ok && i < impl()->frame()->tree()->childCount()) {634 slot.setCustomIndex(this, i, indexGetter);635 return true;636 }637 638 // allow shortcuts like 'Image1' instead of document.images.Image1639 Document* doc = impl()->frame()->document();640 if (doc && doc->isHTMLDocument()) {641 if (!allowsAccessFrom(exec)) {642 slot.setUndefined(this);643 return true;644 }645 646 AtomicString atomicPropertyName = propertyName;647 if (static_cast<HTMLDocument*>(doc)->hasNamedItem(atomicPropertyName) || doc->getElementById(atomicPropertyName)) {648 slot.setCustom(this, namedItemGetter);649 return true;650 }651 }652 653 if (!allowsAccessFrom(exec)) {654 slot.setUndefined(this);655 return true;656 }657 658 return JSObject::getOwnPropertySlot(exec, propertyName, slot);659 }660 661 void Window::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)662 {663 const HashEntry* entry = Lookup::findEntry(&WindowTable, propertyName);664 if (entry) {665 if (entry->attr & Function) {666 if (allowsAccessFrom(exec))667 JSObject::put(exec, propertyName, value, attr);668 return;669 }670 if (entry->attr & ReadOnly)671 return;672 673 switch (entry->value.intValue) {674 case Location_: {675 Frame* p = Window::retrieveActive(exec)->impl()->frame();676 if (p) {677 if (!p->loader()->shouldAllowNavigation(impl()->frame()))678 return;679 String dstUrl = p->loader()->completeURL(value->toString(exec)).string();680 if (!dstUrl.startsWith("javascript:", false) || allowsAccessFrom(exec)) {681 bool userGesture = p->scriptProxy()->processingUserGesture();682 // We want a new history item if this JS was called via a user gesture683 impl()->frame()->loader()->scheduleLocationChange(dstUrl, p->loader()->outgoingReferrer(), false, userGesture);684 }685 }686 return;687 }688 case Onabort:689 if (allowsAccessFrom(exec))690 setListener(exec, abortEvent,value);691 return;692 case Onblur:693 if (allowsAccessFrom(exec))694 setListener(exec, blurEvent,value);695 return;696 case Onchange:697 if (allowsAccessFrom(exec))698 setListener(exec, changeEvent,value);699 return;700 case Onclick:701 if (allowsAccessFrom(exec))702 setListener(exec,clickEvent,value);703 return;704 case Ondblclick:705 if (allowsAccessFrom(exec))706 setListener(exec, dblclickEvent,value);707 return;708 case Onerror:709 if (allowsAccessFrom(exec))710 setListener(exec, errorEvent, value);711 return;712 case Onfocus:713 if (allowsAccessFrom(exec))714 setListener(exec,focusEvent,value);715 return;716 case Onkeydown:717 if (allowsAccessFrom(exec))718 setListener(exec,keydownEvent,value);719 return;720 case Onkeypress:721 if (allowsAccessFrom(exec))722 setListener(exec,keypressEvent,value);723 return;724 case Onkeyup:725 if (allowsAccessFrom(exec))726 setListener(exec,keyupEvent,value);727 return;728 case Onload:729 if (allowsAccessFrom(exec))730 setListener(exec,loadEvent,value);731 return;732 case Onmousedown:733 if (allowsAccessFrom(exec))734 setListener(exec,mousedownEvent,value);735 return;736 case Onmousemove:737 if (allowsAccessFrom(exec))738 setListener(exec,mousemoveEvent,value);739 return;740 case Onmouseout:741 if (allowsAccessFrom(exec))742 setListener(exec,mouseoutEvent,value);743 return;744 case Onmouseover:745 if (allowsAccessFrom(exec))746 setListener(exec,mouseoverEvent,value);747 return;748 case Onmouseup:749 if (allowsAccessFrom(exec))750 setListener(exec,mouseupEvent,value);751 return;752 case OnWindowMouseWheel:753 if (allowsAccessFrom(exec))754 setListener(exec, mousewheelEvent,value);755 return;756 case Onreset:757 if (allowsAccessFrom(exec))758 setListener(exec,resetEvent,value);759 return;760 case Onresize:761 if (allowsAccessFrom(exec))762 setListener(exec,resizeEvent,value);763 return;764 case Onscroll:765 if (allowsAccessFrom(exec))766 setListener(exec,scrollEvent,value);767 return;768 case Onsearch:769 if (allowsAccessFrom(exec))770 setListener(exec,searchEvent,value);771 return;772 case Onselect:773 if (allowsAccessFrom(exec))774 setListener(exec,selectEvent,value);775 return;776 case Onsubmit:777 if (allowsAccessFrom(exec))778 setListener(exec,submitEvent,value);779 return;780 case Onbeforeunload:781 if (allowsAccessFrom(exec))782 setListener(exec, beforeunloadEvent, value);783 return;784 case Onunload:785 if (allowsAccessFrom(exec))786 setListener(exec, unloadEvent, value);787 return;788 default:789 break;790 }791 }792 if (allowsAccessFrom(exec))793 JSObject::put(exec, propertyName, value, attr);794 }795 796 bool Window::allowsAccessFrom(const JSGlobalObject* other) const797 {798 const Frame* originFrame = static_cast<const Window*>(other)->impl()->frame();799 if (!originFrame)800 return false;801 802 const Frame* targetFrame = impl()->frame();803 if (!targetFrame)804 return false;805 806 if (originFrame == targetFrame)807 return true;808 809 WebCore::Document* targetDocument = targetFrame->document();810 811 // JS may be attempting to access the "window" object, which should be valid,812 // even if the document hasn't been constructed yet. If the document doesn't813 // exist yet allow JS to access the window object.814 if (!targetDocument)815 return true;816 817 WebCore::Document* originDocument = originFrame->document();818 819 const SecurityOrigin& originSecurityOrigin = originDocument->securityOrigin();820 const SecurityOrigin& targetSecurityOrigin = targetDocument->securityOrigin();821 822 if (originSecurityOrigin.canAccess(targetSecurityOrigin))823 return true;824 825 if (!targetFrame->settings()->privateBrowsingEnabled()) {826 // FIXME: this error message should contain more specifics of why the same origin check has failed.827 String message = String::format("Unsafe JavaScript attempt to access frame with URL %s from frame with URL %s. Domains, protocols and ports must match.\n",828 targetDocument->url().utf8().data(), originDocument->url().utf8().data());829 830 if (Interpreter::shouldPrintExceptions())831 printf("%s", message.utf8().data());832 833 if (Page* page = targetFrame->page())834 page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, 1, String()); // FIXME: provide a real line number and source URL.835 }836 837 return false;838 }839 840 ExecState* Window::globalExec()841 {842 // We need to make sure that any script execution happening in this843 // frame does not destroy it844 ASSERT(impl()->frame());845 impl()->frame()->keepAlive();846 return JSGlobalObject::globalExec();847 }848 849 bool Window::shouldInterruptScript() const850 {851 ASSERT(impl()->frame());852 Page* page = impl()->frame()->page();853 854 // See <rdar://problem/5479443>. We don't think that page can ever be NULL855 // in this case, but if it is, we've gotten into a state where we may have856 // hung the UI, with no way to ask the client whether to cancel execution.857 // For now, our solution is just to cancel execution no matter what,858 // ensuring that we never hang. We might want to consider other solutions859 // if we discover problems with this one.860 ASSERT(page);861 if (!page)862 return true;863 864 return page->chrome()->shouldInterruptJavaScript();865 }866 867 void Window::setListener(ExecState* exec, const AtomicString& eventType, JSValue* func)868 {869 ASSERT(impl()->frame());870 Document* doc = impl()->frame()->document();871 if (!doc)872 return;873 874 doc->setHTMLWindowEventListener(eventType, findOrCreateJSEventListener(func, true));875 }876 877 JSValue* Window::getListener(ExecState* exec, const AtomicString& eventType) const878 {879 ASSERT(impl()->frame());880 Document* doc = impl()->frame()->document();881 if (!doc)882 return jsUndefined();883 884 WebCore::EventListener* listener = doc->getHTMLWindowEventListener(eventType);885 if (listener && static_cast<JSEventListener*>(listener)->listenerObj())886 return static_cast<JSEventListener*>(listener)->listenerObj();887 return jsNull();888 }889 890 JSEventListener* Window::findJSEventListener(JSValue* val, bool html)891 {892 if (!val->isObject())893 return 0;894 JSObject* object = static_cast<JSObject*>(val);895 ListenersMap& listeners = html ? d->jsHTMLEventListeners : d->jsEventListeners;896 return listeners.get(object);897 }898 899 JSEventListener* Window::findOrCreateJSEventListener(JSValue* val, bool html)900 {901 JSEventListener* listener = findJSEventListener(val, html);902 if (listener)903 return listener;904 905 if (!val->isObject())906 return 0;907 JSObject* object = static_cast<JSObject*>(val);908 909 // Note that the JSEventListener constructor adds it to our jsEventListeners list910 return new JSEventListener(object, this, html);911 }912 913 JSUnprotectedEventListener* Window::findJSUnprotectedEventListener(JSValue* val, bool html)914 {915 if (!val->isObject())916 return 0;917 JSObject* object = static_cast<JSObject*>(val);918 UnprotectedListenersMap& listeners = html ? d->jsUnprotectedHTMLEventListeners : d->jsUnprotectedEventListeners;919 return listeners.get(object);920 }921 922 JSUnprotectedEventListener* Window::findOrCreateJSUnprotectedEventListener(JSValue* val, bool html)923 {924 JSUnprotectedEventListener* listener = findJSUnprotectedEventListener(val, html);925 if (listener)926 return listener;927 if (!val->isObject())928 return 0;929 JSObject* object = static_cast<JSObject*>(val);930 931 // The JSUnprotectedEventListener constructor adds it to our jsUnprotectedEventListeners map.932 return new JSUnprotectedEventListener(object, this, html);933 }934 935 void Window::clearHelperObjectProperties()936 {937 d->loc = 0;938 d->m_evt = 0;939 }940 941 void Window::clear()942 {943 JSLock lock;944 945 if (d->m_returnValueSlot && !*d->m_returnValueSlot)946 *d->m_returnValueSlot = getDirect("returnValue");947 948 clearAllTimeouts();949 clearProperties();950 clearHelperObjectProperties();951 952 // Now recreate a working global object for the next URL that will use us; but only if we haven't been953 // disconnected yet954 if (Frame* frame = impl()->frame())955 frame->scriptProxy()->globalObject()->reset(JSDOMWindowPrototype::self());956 957 // there's likely to be lots of garbage now958 gcController().garbageCollectSoon();959 }960 961 void Window::setCurrentEvent(Event* evt)962 {963 d->m_evt = evt;964 }965 966 Event* Window::currentEvent()967 {968 return d->m_evt;969 }970 971 JSValue* WindowProtoFuncAToB::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)972 {973 if (!thisObj->inherits(&Window::info))974 return throwError(exec, TypeError);975 976 if (args.size() < 1)977 return throwError(exec, SyntaxError, "Not enough arguments");978 979 JSValue* v = args[0];980 if (v->isNull())981 return jsString();982 983 UString s = v->toString(exec);984 if (!s.is8Bit()) {985 setDOMException(exec, INVALID_CHARACTER_ERR);986 return jsUndefined();987 }988 989 Vector<char> in(s.size());990 for (int i = 0; i < s.size(); ++i)991 in[i] = static_cast<char>(s.data()[i].unicode());992 Vector<char> out;993 994 if (!base64Decode(in, out))995 return throwError(exec, GeneralError, "Cannot decode base64");996 997 return jsString(String(out.data(), out.size()));998 }999 1000 JSValue* WindowProtoFuncBToA::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1001 {1002 if (!thisObj->inherits(&Window::info))1003 return throwError(exec, TypeError);1004 1005 if (args.size() < 1)1006 return throwError(exec, SyntaxError, "Not enough arguments");1007 1008 JSValue* v = args[0];1009 if (v->isNull())1010 return jsString();1011 1012 UString s = v->toString(exec);1013 if (!s.is8Bit()) {1014 setDOMException(exec, INVALID_CHARACTER_ERR);1015 return jsUndefined();1016 }1017 1018 Vector<char> in(s.size());1019 for (int i = 0; i < s.size(); ++i)1020 in[i] = static_cast<char>(s.data()[i].unicode());1021 Vector<char> out;1022 1023 base64Encode(in, out);1024 1025 return jsString(String(out.data(), out.size()));1026 }1027 1028 JSValue* WindowProtoFuncOpen::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1029 {1030 if (!thisObj->inherits(&Window::info))1031 return throwError(exec, TypeError);1032 Window* window = static_cast<Window*>(thisObj);1033 Frame* frame = window->impl()->frame();1034 if (!frame)1035 return jsUndefined();1036 Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();1037 if (!activeFrame)1038 return jsUndefined();1039 1040 Page* page = frame->page();1041 1042 String urlString = valueToStringWithUndefinedOrNullCheck(exec, args[0]);1043 AtomicString frameName = args[1]->isUndefinedOrNull() ? "_blank" : AtomicString(args[1]->toString(exec));1044 1045 // Because FrameTree::find() returns true for empty strings, we must check for empty framenames.1046 // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.1047 if (!allowPopUp(frame) && (frameName.isEmpty() || !frame->tree()->find(frameName)))1048 return jsUndefined();1049 1050 // Get the target frame for the special cases of _top and _parent. In those1051 // cases, we can schedule a location change right now and return early.1052 bool topOrParent = false;1053 if (frameName == "_top") {1054 frame = frame->tree()->top();1055 topOrParent = true;1056 } else if (frameName == "_parent") {1057 if (Frame* parent = frame->tree()->parent())1058 frame = parent;1059 if (!activeFrame->loader()->shouldAllowNavigation(frame))1060 return jsUndefined();1061 topOrParent = true;1062 }1063 if (topOrParent) {1064 String completedURL;1065 if (!urlString.isEmpty())1066 completedURL = activeFrame->document()->completeURL(urlString);1067 1068 const Window* targetedWindow = Window::retrieveWindow(frame);1069 if (!completedURL.isEmpty() && (!completedURL.startsWith("javascript:", false) || (targetedWindow && targetedWindow->allowsAccessFrom(exec)))) {1070 bool userGesture = activeFrame->scriptProxy()->processingUserGesture();1071 frame->loader()->scheduleLocationChange(completedURL, activeFrame->loader()->outgoingReferrer(), false, userGesture);1072 }1073 return Window::retrieve(frame);1074 }1075 1076 // In the case of a named frame or a new window, we'll use the createWindow() helper1077 WindowFeatures windowFeatures(valueToStringWithUndefinedOrNullCheck(exec, args[2]));1078 FloatRect windowRect(windowFeatures.x, windowFeatures.y, windowFeatures.width, windowFeatures.height);1079 WebCore::DOMWindow::adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), windowRect, windowRect);1080 1081 windowFeatures.x = windowRect.x();1082 windowFeatures.y = windowRect.y();1083 windowFeatures.height = windowRect.height();1084 windowFeatures.width = windowRect.width();1085 1086 frame = createWindow(exec, frame, urlString, frameName, windowFeatures, 0);1087 1088 if (!frame)1089 return jsUndefined();1090 1091 return Window::retrieve(frame); // global object1092 }1093 1094 JSValue* WindowProtoFuncSetTimeout::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1095 {1096 if (!thisObj->inherits(&Window::info))1097 return throwError(exec, TypeError);1098 Window* window = static_cast<Window*>(thisObj);1099 1100 JSValue* v = args[0];1101 if (v->isString())1102 return jsNumber(window->installTimeout(v->toString(exec), args[1]->toInt32(exec), true /*single shot*/));1103 if (v->isObject() && static_cast<JSObject*>(v)->implementsCall()) {1104 List argsTail;1105 args.getSlice(2, argsTail);1106 return jsNumber(window->installTimeout(v, argsTail, args[1]->toInt32(exec), true /*single shot*/));1107 }1108 1109 return jsUndefined();1110 }1111 1112 JSValue* WindowProtoFuncClearTimeout::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1113 {1114 // Also the implementation for window.clearInterval()1115 1116 if (!thisObj->inherits(&Window::info))1117 return throwError(exec, TypeError);1118 Window* window = static_cast<Window*>(thisObj);1119 1120 window->clearTimeout(args[0]->toInt32(exec));1121 return jsUndefined();1122 }1123 1124 JSValue* WindowProtoFuncSetInterval::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1125 {1126 if (!thisObj->inherits(&Window::info))1127 return throwError(exec, TypeError);1128 Window* window = static_cast<Window*>(thisObj);1129 1130 if (args.size() >= 2) {1131 JSValue* v = args[0];1132 int delay = args[1]->toInt32(exec);1133 if (v->isString())1134 return jsNumber(window->installTimeout(v->toString(exec), delay, false));1135 if (v->isObject() && static_cast<JSObject*>(v)->implementsCall()) {1136 List argsTail;1137 args.getSlice(2, argsTail);1138 return jsNumber(window->installTimeout(v, argsTail, delay, false));1139 }1140 }1141 1142 return jsUndefined();1143 1144 }1145 1146 JSValue* WindowProtoFuncAddEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1147 {1148 if (!thisObj->inherits(&Window::info))1149 return throwError(exec, TypeError);1150 Window* window = static_cast<Window*>(thisObj);1151 Frame* frame = window->impl()->frame();1152 if (!frame)1153 return jsUndefined();1154 1155 if (JSEventListener* listener = window->findOrCreateJSEventListener(args[1])) {1156 if (Document* doc = frame->document())1157 doc->addWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec));1158 }1159 1160 return jsUndefined();1161 }1162 1163 JSValue* WindowProtoFuncRemoveEventListener::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1164 {1165 if (!thisObj->inherits(&Window::info))1166 return throwError(exec, TypeError);1167 Window* window = static_cast<Window*>(thisObj);1168 Frame* frame = window->impl()->frame();1169 if (!frame)1170 return jsUndefined();1171 1172 if (JSEventListener* listener = window->findJSEventListener(args[1])) {1173 if (Document* doc = frame->document())1174 doc->removeWindowEventListener(AtomicString(args[0]->toString(exec)), listener, args[2]->toBoolean(exec));1175 }1176 1177 return jsUndefined();1178 }1179 1180 JSValue* WindowProtoFuncShowModalDialog::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1181 {1182 if (!thisObj->inherits(&Window::info))1183 return throwError(exec, TypeError);1184 Window* window = static_cast<Window*>(thisObj);1185 Frame* frame = window->impl()->frame();1186 if (!frame)1187 return jsUndefined();1188 1189 return showModalDialog(exec, frame, valueToStringWithUndefinedOrNullCheck(exec, args[0]), args[1], valueToStringWithUndefinedOrNullCheck(exec, args[2]));1190 }1191 1192 JSValue* WindowProtoFuncNotImplemented::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1193 {1194 if (!thisObj->inherits(&Window::info))1195 return throwError(exec, TypeError);1196 1197 return jsUndefined();1198 }1199 1200 void Window::setReturnValueSlot(JSValue** slot)1201 {1202 d->m_returnValueSlot = slot;1203 }1204 1205 ////////////////////// ScheduledAction ////////////////////////1206 48 1207 49 void ScheduledAction::execute(Window* window) … … 1227 69 List args; 1228 70 size_t size = m_args.size(); 1229 for (size_t i = 0; i < size; ++i) {71 for (size_t i = 0; i < size; ++i) 1230 72 args.append(m_args[i]); 1231 }1232 73 1233 74 globalObject->startTimeoutCheck(); … … 1259 100 } 1260 101 1261 ////////////////////// timeouts ////////////////////////1262 1263 void Window::clearAllTimeouts()1264 {1265 deleteAllValues(d->m_timeouts);1266 d->m_timeouts.clear();1267 }1268 1269 int Window::installTimeout(ScheduledAction* a, int t, bool singleShot)1270 {1271 int timeoutId = ++lastUsedTimeoutId;1272 1273 // avoid wraparound going negative on us1274 if (timeoutId <= 0)1275 timeoutId = 1;1276 1277 int nestLevel = timerNestingLevel + 1;1278 DOMWindowTimer* timer = new DOMWindowTimer(timeoutId, nestLevel, this, a);1279 ASSERT(!d->m_timeouts.get(timeoutId));1280 d->m_timeouts.set(timeoutId, timer);1281 // Use a minimum interval of 10 ms to match other browsers, but only once we've1282 // nested enough to notice that we're repeating.1283 // Faster timers might be "better", but they're incompatible.1284 double interval = max(0.001, t * 0.001);1285 if (interval < cMinimumTimerInterval && nestLevel >= cMaxTimerNestingLevel)1286 interval = cMinimumTimerInterval;1287 if (singleShot)1288 timer->startOneShot(interval);1289 else1290 timer->startRepeating(interval);1291 return timeoutId;1292 }1293 1294 ScheduledAction::ScheduledAction(JSValue* func, const List& args)1295 : m_func(func)1296 {1297 List::const_iterator end = args.end();1298 for (List::const_iterator it = args.begin(); it != end; ++it)1299 m_args.append(*it);1300 }1301 1302 int Window::installTimeout(const UString& handler, int t, bool singleShot)1303 {1304 return installTimeout(new ScheduledAction(handler), t, singleShot);1305 }1306 1307 int Window::installTimeout(JSValue* func, const List& args, int t, bool singleShot)1308 {1309 return installTimeout(new ScheduledAction(func, args), t, singleShot);1310 }1311 1312 WebCore::PausedTimeouts* Window::pauseTimeouts()1313 {1314 size_t count = d->m_timeouts.size();1315 if (count == 0)1316 return 0;1317 1318 PausedTimeout* t = new PausedTimeout [count];1319 PausedTimeouts* result = new PausedTimeouts(t, count);1320 1321 WindowPrivate::TimeoutsMap::iterator it = d->m_timeouts.begin();1322 for (size_t i = 0; i != count; ++i, ++it) {1323 int timeoutId = it->first;1324 DOMWindowTimer* timer = it->second;1325 t[i].timeoutId = timeoutId;1326 t[i].nestingLevel = timer->nestingLevel();1327 t[i].nextFireInterval = timer->nextFireInterval();1328 t[i].repeatInterval = timer->repeatInterval();1329 t[i].action = timer->takeAction();1330 }1331 ASSERT(it == d->m_timeouts.end());1332 1333 deleteAllValues(d->m_timeouts);1334 d->m_timeouts.clear();1335 1336 return result;1337 }1338 1339 void Window::resumeTimeouts(PausedTimeouts* timeouts)1340 {1341 if (!timeouts)1342 return;1343 size_t count = timeouts->numTimeouts();1344 PausedTimeout* array = timeouts->takeTimeouts();1345 for (size_t i = 0; i != count; ++i) {1346 int timeoutId = array[i].timeoutId;1347 DOMWindowTimer* timer = new DOMWindowTimer(timeoutId, array[i].nestingLevel, this, array[i].action);1348 d->m_timeouts.set(timeoutId, timer);1349 timer->start(array[i].nextFireInterval, array[i].repeatInterval);1350 }1351 delete [] array;1352 }1353 1354 void Window::clearTimeout(int timeoutId, bool delAction)1355 {1356 // timeout IDs have to be positive, and 0 and -1 are unsafe to1357 // even look up since they are the empty and deleted value1358 // respectively1359 if (timeoutId <= 0)1360 return;1361 1362 delete d->m_timeouts.take(timeoutId);1363 }1364 1365 void Window::timerFired(DOMWindowTimer* timer)1366 {1367 // Simple case for non-one-shot timers.1368 if (timer->isActive()) {1369 int timeoutId = timer->timeoutId();1370 1371 timer->action()->execute(this);1372 if (d->m_timeouts.contains(timeoutId) && timer->repeatInterval() && timer->repeatInterval() < cMinimumTimerInterval) {1373 timer->setNestingLevel(timer->nestingLevel() + 1);1374 if (timer->nestingLevel() >= cMaxTimerNestingLevel)1375 timer->augmentRepeatInterval(cMinimumTimerInterval - timer->repeatInterval());1376 }1377 return;1378 }1379 1380 // Delete timer before executing the action for one-shot timers.1381 ScheduledAction* action = timer->takeAction();1382 d->m_timeouts.remove(timer->timeoutId());1383 delete timer;1384 action->execute(this);1385 1386 JSLock lock;1387 delete action;1388 }1389 1390 void Window::disconnectFrame()1391 {1392 clearAllTimeouts();1393 if (d->loc)1394 d->loc->m_frame = 0;1395 }1396 1397 Window::ListenersMap& Window::jsEventListeners()1398 {1399 return d->jsEventListeners;1400 }1401 1402 Window::ListenersMap& Window::jsHTMLEventListeners()1403 {1404 return d->jsHTMLEventListeners;1405 }1406 1407 Window::UnprotectedListenersMap& Window::jsUnprotectedEventListeners()1408 {1409 return d->jsUnprotectedEventListeners;1410 }1411 1412 Window::UnprotectedListenersMap& Window::jsUnprotectedHTMLEventListeners()1413 {1414 return d->jsUnprotectedHTMLEventListeners;1415 }1416 1417 ////////////////////// Location Object ////////////////////////1418 1419 const ClassInfo Location::info = { "Location", 0, &LocationTable };1420 /*1421 @begin LocationTable 121422 assign &LocationProtoFuncAssign::create DontDelete|Function 11423 hash Location::Hash DontDelete1424 host Location::Host DontDelete1425 hostname Location::Hostname DontDelete1426 href Location::Href DontDelete1427 pathname Location::Pathname DontDelete1428 port Location::Port DontDelete1429 protocol Location::Protocol DontDelete1430 search Location::Search DontDelete1431 toString &LocationProtoFuncToString::create DontEnum|DontDelete|Function 01432 replace &LocationProtoFuncReplace::create DontDelete|Function 11433 reload &LocationProtoFuncReload::create DontDelete|Function 01434 @end1435 */1436 1437 Location::Location(Frame* frame)1438 : m_frame(frame)1439 {1440 }1441 1442 JSValue *Location::getValueProperty(ExecState* exec, int token) const1443 {1444 KURL url = m_frame->loader()->url();1445 switch (token) {1446 case Hash:1447 return jsString(url.ref().isNull() ? "" : "#" + url.ref());1448 case Host: {1449 // Note: this is the IE spec. The NS spec swaps the two, it says1450 // "The hostname property is the concatenation of the host and port properties, separated by a colon."1451 // Bleh.1452 UString str = url.host();1453 if (url.port())1454 str += ":" + String::number((int)url.port());1455 return jsString(str);1456 }1457 case Hostname:1458 return jsString(url.host());1459 case Href:1460 if (!url.hasPath())1461 return jsString(url.prettyURL() + "/");1462 return jsString(url.prettyURL());1463 case Pathname:1464 return jsString(url.path().isEmpty() ? "/" : url.path());1465 case Port:1466 return jsString(url.port() ? String::number((int)url.port()) : "");1467 case Protocol:1468 return jsString(url.protocol() + ":");1469 case Search:1470 return jsString(url.query());1471 default:1472 ASSERT_NOT_REACHED();1473 return jsUndefined();1474 }1475 }1476 1477 bool Location::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)1478 {1479 if (!m_frame)1480 return false;1481 1482 const Window* window = Window::retrieveWindow(m_frame);1483 1484 const HashEntry* entry = Lookup::findEntry(&LocationTable, propertyName);1485 if (!entry || !(entry->attr & KJS::Function) || (entry->value.functionValue != &LocationProtoFuncReplace::create1486 && entry->value.functionValue != &LocationProtoFuncReload::create1487 && entry->value.functionValue != &LocationProtoFuncAssign::create)) {1488 if (!window || !window->allowsAccessFrom(exec)) {1489 slot.setUndefined(this);1490 return true;1491 }1492 }1493 1494 return getStaticPropertySlot<Location, JSObject>(exec, &LocationTable, this, propertyName, slot);1495 }1496 1497 void Location::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)1498 {1499 if (!m_frame)1500 return;1501 1502 DeprecatedString str = value->toString(exec);1503 KURL url = m_frame->loader()->url();1504 const Window* window = Window::retrieveWindow(m_frame);1505 bool sameDomainAccess = window && window->allowsAccessFrom(exec);1506 1507 const HashEntry* entry = Lookup::findEntry(&LocationTable, propertyName);1508 1509 if (entry) {1510 // cross-domain access to the location is allowed when assigning the whole location,1511 // but not when assigning the individual pieces, since that might inadvertently1512 // disclose other parts of the original location.1513 if (entry->value.intValue != Href && !sameDomainAccess)1514 return;1515 1516 switch (entry->value.intValue) {1517 case Href: {1518 Frame* frame = Window::retrieveActive(exec)->impl()->frame();1519 if (!frame)1520 return;1521 if (!frame->loader()->shouldAllowNavigation(m_frame))1522 return;1523 url = frame->loader()->completeURL(str);1524 break;1525 }1526 case Hash: {1527 if (str.startsWith("#"))1528 str = str.mid(1);1529 if (url.ref() == str)1530 return;1531 url.setRef(str);1532 break;1533 }1534 case Host: {1535 url.setHostAndPort(str);1536 break;1537 }1538 case Hostname:1539 url.setHost(str);1540 break;1541 case Pathname:1542 url.setPath(str);1543 break;1544 case Port:1545 url.setPort(str.toUInt());1546 break;1547 case Protocol:1548 url.setProtocol(str);1549 break;1550 case Search:1551 url.setQuery(str);1552 break;1553 default:1554 // Disallow changing other properties in LocationTable. e.g., "window.location.toString = ...".1555 // <http://bugs.webkit.org/show_bug.cgi?id=12720>1556 return;1557 }1558 } else {1559 if (sameDomainAccess)1560 JSObject::put(exec, propertyName, value, attr);1561 return;1562 }1563 1564 Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();1565 if (!url.deprecatedString().startsWith("javascript:", false) || sameDomainAccess) {1566 bool userGesture = activeFrame->scriptProxy()->processingUserGesture();1567 m_frame->loader()->scheduleLocationChange(url.string(), activeFrame->loader()->outgoingReferrer(), false, userGesture);1568 }1569 }1570 1571 JSValue* LocationProtoFuncReplace::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1572 {1573 if (!thisObj->inherits(&Location::info))1574 return throwError(exec, TypeError);1575 Location* location = static_cast<Location*>(thisObj);1576 Frame* frame = location->frame();1577 if (!frame)1578 return jsUndefined();1579 1580 Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();1581 if (activeFrame) {1582 if (!activeFrame->loader()->shouldAllowNavigation(frame))1583 return jsUndefined();1584 DeprecatedString str = args[0]->toString(exec);1585 const Window* window = Window::retrieveWindow(frame);1586 if (!str.startsWith("javascript:", false) || (window && window->allowsAccessFrom(exec))) {1587 bool userGesture = activeFrame->scriptProxy()->processingUserGesture();1588 frame->loader()->scheduleLocationChange(activeFrame->loader()->completeURL(str).string(), activeFrame->loader()->outgoingReferrer(), true, userGesture);1589 }1590 }1591 1592 return jsUndefined();1593 }1594 1595 JSValue* LocationProtoFuncReload::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1596 {1597 if (!thisObj->inherits(&Location::info))1598 return throwError(exec, TypeError);1599 Location* location = static_cast<Location*>(thisObj);1600 Frame* frame = location->frame();1601 if (!frame)1602 return jsUndefined();1603 1604 Window* window = Window::retrieveWindow(frame);1605 if (!window->allowsAccessFrom(exec))1606 return jsUndefined();1607 1608 if (!frame->loader()->url().deprecatedString().startsWith("javascript:", false) || (window && window->allowsAccessFrom(exec))) {1609 bool userGesture = Window::retrieveActive(exec)->impl()->frame()->scriptProxy()->processingUserGesture();1610 frame->loader()->scheduleRefresh(userGesture);1611 }1612 return jsUndefined();1613 }1614 1615 JSValue* LocationProtoFuncAssign::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1616 {1617 if (!thisObj->inherits(&Location::info))1618 return throwError(exec, TypeError);1619 Location* location = static_cast<Location*>(thisObj);1620 Frame* frame = location->frame();1621 if (!frame)1622 return jsUndefined();1623 1624 Frame* activeFrame = Window::retrieveActive(exec)->impl()->frame();1625 if (activeFrame) {1626 if (!activeFrame->loader()->shouldAllowNavigation(frame))1627 return jsUndefined();1628 const Window* window = Window::retrieveWindow(frame);1629 String dstUrl = activeFrame->loader()->completeURL(args[0]->toString(exec)).string();1630 if (!dstUrl.startsWith("javascript:", false) || (window && window->allowsAccessFrom(exec))) {1631 bool userGesture = activeFrame->scriptProxy()->processingUserGesture();1632 // We want a new history item if this JS was called via a user gesture1633 frame->loader()->scheduleLocationChange(dstUrl, activeFrame->loader()->outgoingReferrer(), false, userGesture);1634 }1635 }1636 1637 return jsUndefined();1638 }1639 1640 JSValue* LocationProtoFuncToString::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)1641 {1642 if (!thisObj->inherits(&Location::info))1643 return throwError(exec, TypeError);1644 Location* location = static_cast<Location*>(thisObj);1645 Frame* frame = location->frame();1646 if (!frame)1647 return jsUndefined();1648 1649 const KURL& url = frame->loader()->url();1650 if (!url.hasPath())1651 return jsString(url.prettyURL() + "/");1652 return jsString(url.prettyURL());1653 }1654 1655 /////////////////////////////////////////////////////////////////////////////1656 1657 void DOMWindowTimer::fired()1658 {1659 timerNestingLevel = m_nestingLevel;1660 m_object->timerFired(this);1661 timerNestingLevel = 0;1662 }1663 1664 } // namespace KJS1665 1666 using namespace KJS;1667 1668 namespace WebCore {1669 1670 JSValue* toJS(ExecState*, DOMWindow* domWindow)1671 {1672 if (!domWindow)1673 return jsNull();1674 Frame* frame = domWindow->frame();1675 if (!frame)1676 return jsNull();1677 return Window::retrieve(frame);1678 }1679 1680 102 } // namespace WebCore -
trunk/WebCore/bindings/js/ScheduledAction.h
r28779 r28794 18 18 */ 19 19 20 #ifndef kjs_window_h21 #define kjs_window_h20 #ifndef ScheduledAction_h 21 #define ScheduledAction_h 22 22 23 23 #include "PlatformString.h" 24 #include "kjs_binding.h"25 24 #include <kjs/protect.h> 26 #include <wtf/HashMap.h> 27 #include <wtf/Noncopyable.h> 28 #include <wtf/OwnPtr.h> 25 #include <wtf/Vector.h> 26 27 namespace KJS { 28 class Window; 29 class JSValue; 30 class List; 31 } 29 32 30 33 namespace WebCore { 31 class AtomicString;32 class DOMWindow;33 class Frame;34 class JSEventListener;35 class JSUnprotectedEventListener;36 class PausedTimeouts;37 }38 39 namespace KJS {40 41 class DOMWindowTimer;42 class Location;43 class ScheduledAction;44 class Window;45 class WindowFunc;46 class WindowPrivate;47 48 // This is the only WebCore JS binding which does not inherit from DOMObject49 class Window : public JSGlobalObject {50 friend class Location;51 friend class ScheduledAction;52 protected:53 Window(WebCore::DOMWindow*);54 55 public:56 virtual ~Window();57 58 WebCore::DOMWindow* impl() const { return m_impl.get(); }59 60 void disconnectFrame();61 62 // Returns and registers a window object. In case there's already a Window63 // for the specified frame p this will be returned in order to have unique64 // bindings.65 static JSValue* retrieve(WebCore::Frame*);66 67 // Returns the Window object for a given HTML frame68 static Window* retrieveWindow(WebCore::Frame*);69 70 // Returns a pointer to the Window object this javascript interpreting instance71 // was called from.72 static Window* retrieveActive(ExecState*);73 74 virtual void mark();75 76 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);77 JSValue* getValueProperty(ExecState*, int token) const;78 virtual void put(ExecState*, const Identifier& propertyName, JSValue*, int attr = None);79 80 int installTimeout(const UString& handler, int t, bool singleShot);81 int installTimeout(JSValue* function, const List& args, int t, bool singleShot);82 void clearTimeout(int timerId, bool delAction = true);83 WebCore::PausedTimeouts* pauseTimeouts();84 void resumeTimeouts(WebCore::PausedTimeouts*);85 86 void timerFired(DOMWindowTimer*);87 88 Location* location() const;89 90 // Finds a wrapper of a JS EventListener, returns 0 if no existing one.91 WebCore::JSEventListener* findJSEventListener(JSValue*, bool html = false);92 93 // Finds or creates a wrapper of a JS EventListener. JS EventListener object is GC-protected.94 WebCore::JSEventListener *findOrCreateJSEventListener(JSValue*, bool html = false);95 96 // Finds a wrapper of a GC-unprotected JS EventListener, returns 0 if no existing one.97 WebCore::JSUnprotectedEventListener* findJSUnprotectedEventListener(JSValue*, bool html = false);98 99 // Finds or creates a wrapper of a JS EventListener. JS EventListener object is *NOT* GC-protected.100 WebCore::JSUnprotectedEventListener *findOrCreateJSUnprotectedEventListener(JSValue*, bool html = false);101 102 void clear();103 104 void setCurrentEvent(WebCore::Event*);105 WebCore::Event* currentEvent();106 107 // Set a place to put a dialog return value when the window is cleared.108 void setReturnValueSlot(JSValue** slot);109 110 typedef HashMap<JSObject*, WebCore::JSEventListener*> ListenersMap;111 typedef HashMap<JSObject*, WebCore::JSUnprotectedEventListener*> UnprotectedListenersMap;112 113 ListenersMap& jsEventListeners();114 ListenersMap& jsHTMLEventListeners();115 UnprotectedListenersMap& jsUnprotectedEventListeners();116 UnprotectedListenersMap& jsUnprotectedHTMLEventListeners();117 118 virtual const ClassInfo* classInfo() const { return &info; }119 static const ClassInfo info;120 121 virtual ExecState* globalExec();122 123 virtual bool shouldInterruptScript() const;124 125 virtual bool allowsAccessFrom(const JSGlobalObject*) const;126 bool allowsAccessFrom(ExecState* exec) const { return allowsAccessFrom(exec->dynamicGlobalObject()); }127 128 enum {129 // Attributes130 Crypto, Event_, Location_, Navigator_,131 ClientInformation,132 133 // Event Listeners134 Onabort, Onblur, Onchange, Onclick,135 Ondblclick, Onerror, Onfocus, Onkeydown,136 Onkeypress, Onkeyup, Onload, Onmousedown,137 Onmousemove, Onmouseout, Onmouseover, Onmouseup,138 OnWindowMouseWheel, Onreset, Onresize, Onscroll,139 Onsearch, Onselect, Onsubmit, Onunload,140 Onbeforeunload,141 142 // Constructors143 DOMException, Audio, Image, Option, XMLHttpRequest,144 XSLTProcessor_145 };146 147 private:148 JSValue* getListener(ExecState*, const WebCore::AtomicString& eventType) const;149 void setListener(ExecState*, const WebCore::AtomicString& eventType, JSValue* func);150 151 static JSValue* childFrameGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);152 static JSValue* namedFrameGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);153 static JSValue* indexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);154 static JSValue* namedItemGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);155 156 void clearHelperObjectProperties();157 void clearAllTimeouts();158 int installTimeout(ScheduledAction*, int interval, bool singleShot);159 160 RefPtr<WebCore::DOMWindow> m_impl;161 OwnPtr<WindowPrivate> d;162 };163 164 #define FOR_EACH_CLASS(macro) \165 macro(WindowProtoFuncAToB) \166 macro(WindowProtoFuncBToA) \167 macro(WindowProtoFuncOpen) \168 macro(WindowProtoFuncSetTimeout) \169 macro(WindowProtoFuncClearTimeout) \170 macro(WindowProtoFuncSetInterval) \171 macro(WindowProtoFuncAddEventListener) \172 macro(WindowProtoFuncRemoveEventListener) \173 macro(WindowProtoFuncShowModalDialog) \174 macro(WindowProtoFuncNotImplemented) \175 176 FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)177 #undef FOR_EACH_CLASS178 179 34 180 35 /** … … 185 40 class ScheduledAction { 186 41 public: 187 ScheduledAction( JSValue* func, constList& args);188 ScheduledAction(const WebCore::String& code)42 ScheduledAction(KJS::JSValue* func, const KJS::List& args); 43 ScheduledAction(const String& code) 189 44 : m_code(code) 190 45 { 191 46 } 192 47 193 void execute( Window*);48 void execute(KJS::Window*); 194 49 195 50 private: 196 ProtectedPtr<JSValue> m_func;197 Vector< ProtectedPtr<JSValue> > m_args;198 WebCore::String m_code;51 KJS::ProtectedPtr<KJS::JSValue> m_func; 52 Vector<KJS::ProtectedPtr<KJS::JSValue> > m_args; 53 String m_code; 199 54 }; 200 55 201 class Location : public DOMObject {202 friend class Window;203 public:204 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);205 JSValue* getValueProperty(ExecState*, int token) const;206 virtual void put(ExecState*, const Identifier& propertyName, JSValue*, int attr = None);207 208 enum { Hash, Href, Hostname, Host, Pathname, Port, Protocol, Search,209 Replace, Reload, ToString, Assign };210 211 WebCore::Frame* frame() const { return m_frame; }212 213 virtual const ClassInfo* classInfo() const { return &info; }214 static const ClassInfo info;215 216 private:217 Location(WebCore::Frame*);218 219 WebCore::Frame* m_frame;220 };221 222 #define FOR_EACH_CLASS(macro) \223 macro(LocationProtoFuncAssign) \224 macro(LocationProtoFuncToString) \225 macro(LocationProtoFuncReplace) \226 macro(LocationProtoFuncReload) \227 228 FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_FUNCTION_WITH_CREATE)229 #undef FOR_EACH_CLASS230 231 } // namespace KJS232 233 namespace WebCore {234 KJS::JSValue* toJS(KJS::ExecState*, DOMWindow*);235 56 } // namespace WebCore 236 57 237 #endif // kjs_window_h58 #endif // ScheduledAction_h -
trunk/WebCore/bindings/js/kjs_window.cpp
r28779 r28794 53 53 #include "PlugInInfoStore.h" 54 54 #include "RenderView.h" 55 #include "ScheduledAction.h" 55 56 #include "SecurityOrigin.h" 56 57 #include "Settings.h" … … 100 101 class DOMWindowTimer : public TimerBase { 101 102 public: 102 DOMWindowTimer(int timeoutId, int nestingLevel, Window* object, ScheduledAction* action)103 DOMWindowTimer(int timeoutId, int nestingLevel, Window* object, WebCore::ScheduledAction* action) 103 104 : m_timeoutId(timeoutId) 104 105 , m_nestingLevel(nestingLevel) … … 119 120 void setNestingLevel(int n) { m_nestingLevel = n; } 120 121 121 ScheduledAction* action() const { return m_action; }122 ScheduledAction* takeAction() {ScheduledAction* a = m_action; m_action = 0; return a; }122 WebCore::ScheduledAction* action() const { return m_action; } 123 WebCore::ScheduledAction* takeAction() { WebCore::ScheduledAction* a = m_action; m_action = 0; return a; } 123 124 124 125 private: … … 128 129 int m_nestingLevel; 129 130 Window* m_object; 130 ScheduledAction* m_action;131 WebCore::ScheduledAction* m_action; 131 132 }; 132 133 … … 1203 1204 } 1204 1205 1205 ////////////////////// ScheduledAction ////////////////////////1206 1207 void ScheduledAction::execute(Window* window)1208 {1209 RefPtr<Frame> frame = window->impl()->frame();1210 if (!frame)1211 return;1212 1213 KJSProxy* scriptProxy = frame->scriptProxy();1214 if (!scriptProxy)1215 return;1216 1217 Window* globalObject = scriptProxy->globalObject();1218 1219 scriptProxy->setProcessingTimerCallback(true);1220 1221 if (JSValue* func = m_func.get()) {1222 JSLock lock;1223 if (func->isObject() && static_cast<JSObject*>(func)->implementsCall()) {1224 ExecState* exec = window->globalExec();1225 ASSERT(window == globalObject);1226 1227 List args;1228 size_t size = m_args.size();1229 for (size_t i = 0; i < size; ++i) {1230 args.append(m_args[i]);1231 }1232 1233 globalObject->startTimeoutCheck();1234 static_cast<JSObject*>(func)->call(exec, window, args);1235 globalObject->stopTimeoutCheck();1236 if (exec->hadException()) {1237 JSObject* exception = exec->exception()->toObject(exec);1238 exec->clearException();1239 String message = exception->get(exec, exec->propertyNames().message)->toString(exec);1240 int lineNumber = exception->get(exec, "line")->toInt32(exec);1241 if (Interpreter::shouldPrintExceptions())1242 printf("(timer):%s\n", message.utf8().data());1243 if (Page* page = frame->page())1244 page->chrome()->addMessageToConsole(JSMessageSource, ErrorMessageLevel, message, lineNumber, String());1245 }1246 }1247 } else1248 frame->loader()->executeScript(m_code);1249 1250 // Update our document's rendering following the execution of the timeout callback.1251 // FIXME: Why not use updateDocumentsRendering to update rendering of all documents?1252 // FIXME: Is this really the right point to do the update? We need a place that works1253 // for all possible entry points that might possibly execute script, but this seems1254 // to be a bit too low-level.1255 if (Document* doc = frame->document())1256 doc->updateRendering();1257 1258 scriptProxy->setProcessingTimerCallback(false);1259 }1260 1261 1206 ////////////////////// timeouts //////////////////////// 1262 1207 … … 1267 1212 } 1268 1213 1269 int Window::installTimeout( ScheduledAction* a, int t, bool singleShot)1214 int Window::installTimeout(WebCore::ScheduledAction* a, int t, bool singleShot) 1270 1215 { 1271 1216 int timeoutId = ++lastUsedTimeoutId; … … 1292 1237 } 1293 1238 1294 ScheduledAction::ScheduledAction(JSValue* func, const List& args)1295 : m_func(func)1296 {1297 List::const_iterator end = args.end();1298 for (List::const_iterator it = args.begin(); it != end; ++it)1299 m_args.append(*it);1300 }1301 1302 1239 int Window::installTimeout(const UString& handler, int t, bool singleShot) 1303 1240 { 1304 return installTimeout(new ScheduledAction(handler), t, singleShot);1241 return installTimeout(new WebCore::ScheduledAction(handler), t, singleShot); 1305 1242 } 1306 1243 1307 1244 int Window::installTimeout(JSValue* func, const List& args, int t, bool singleShot) 1308 1245 { 1309 return installTimeout(new ScheduledAction(func, args), t, singleShot);1246 return installTimeout(new WebCore::ScheduledAction(func, args), t, singleShot); 1310 1247 } 1311 1248 … … 1379 1316 1380 1317 // Delete timer before executing the action for one-shot timers. 1381 ScheduledAction* action = timer->takeAction();1318 WebCore::ScheduledAction* action = timer->takeAction(); 1382 1319 d->m_timeouts.remove(timer->timeoutId()); 1383 1320 delete timer; -
trunk/WebCore/bindings/js/kjs_window.h
r28779 r28794 35 35 class JSUnprotectedEventListener; 36 36 class PausedTimeouts; 37 class ScheduledAction; 37 38 } 38 39 … … 41 42 class DOMWindowTimer; 42 43 class Location; 43 class ScheduledAction;44 44 class Window; 45 45 class WindowFunc; … … 49 49 class Window : public JSGlobalObject { 50 50 friend class Location; 51 friend class ScheduledAction;51 friend class WebCore::ScheduledAction; 52 52 protected: 53 53 Window(WebCore::DOMWindow*); … … 156 156 void clearHelperObjectProperties(); 157 157 void clearAllTimeouts(); 158 int installTimeout( ScheduledAction*, int interval, bool singleShot);158 int installTimeout(WebCore::ScheduledAction*, int interval, bool singleShot); 159 159 160 160 RefPtr<WebCore::DOMWindow> m_impl; … … 178 178 179 179 180 /**181 * An action (either function or string) to be executed after a specified182 * time interval, either once or repeatedly. Used for window.setTimeout()183 * and window.setInterval()184 */185 class ScheduledAction {186 public:187 ScheduledAction(JSValue* func, const List& args);188 ScheduledAction(const WebCore::String& code)189 : m_code(code)190 {191 }192 193 void execute(Window *);194 195 private:196 ProtectedPtr<JSValue> m_func;197 Vector<ProtectedPtr<JSValue> > m_args;198 WebCore::String m_code;199 };200 201 180 class Location : public DOMObject { 202 181 friend class Window;
Note: See TracChangeset
for help on using the changeset viewer.