| Differences between
and this patch
- WebCore/ChangeLog +28 lines
Lines 1-3 WebCore/ChangeLog_sec1
1
2007-12-16  Sam Weinig  <sam@webkit.org>
2
3
        Reviewed by NOBODY (OOPS!).
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
2007-12-16  Sam Weinig  <sam@webkit.org>
29
2007-12-16  Sam Weinig  <sam@webkit.org>
2
30
3
        Reviewed by Darin.
31
        Reviewed by Darin.
- WebCore/WebCore.pro +1 lines
Lines 419-424 SOURCES += \ WebCore/WebCore.pro_sec1
419
    bindings/js/kjs_proxy.cpp \
419
    bindings/js/kjs_proxy.cpp \
420
    bindings/js/kjs_window.cpp \
420
    bindings/js/kjs_window.cpp \
421
    bindings/js/PausedTimeouts.cpp \
421
    bindings/js/PausedTimeouts.cpp \
422
    bindings/js/ScheduledAction.cpp \
422
    css/CSSBorderImageValue.cpp \
423
    css/CSSBorderImageValue.cpp \
423
    css/CSSCharsetRule.cpp \
424
    css/CSSCharsetRule.cpp \
424
    css/CSSComputedStyleDeclaration.cpp \
425
    css/CSSComputedStyleDeclaration.cpp \
- WebCore/WebCoreSources.bkl +1 lines
Lines 93-98 This file contains the list of files nee WebCore/WebCoreSources.bkl_sec1
93
        bindings/js/kjs_proxy.cpp
93
        bindings/js/kjs_proxy.cpp
94
        bindings/js/kjs_window.cpp
94
        bindings/js/kjs_window.cpp
95
        bindings/js/PausedTimeouts.cpp
95
        bindings/js/PausedTimeouts.cpp
96
        bindings/js/ScheduledAction.cpp
96
    </set>
97
    </set>
97
    
98
    
98
    <set append="1" var="WEBCORE_SOURCES_CSS">
99
    <set append="1" var="WEBCORE_SOURCES_CSS">
- WebCore/WebCore.vcproj/WebCore.vcproj +8 lines
Lines 7655-7660 WebCore/WebCore.vcproj/WebCore.vcproj_sec1
7655
					RelativePath="..\bindings\js\PausedTimeouts.h"
7655
					RelativePath="..\bindings\js\PausedTimeouts.h"
7656
					>
7656
					>
7657
				</File>
7657
				</File>
7658
				<File
7659
					RelativePath="..\bindings\js\ScheduledAction.cpp"
7660
					>
7661
				</File>
7662
				<File
7663
					RelativePath="..\bindings\js\ScheduledAction.h"
7664
					>
7665
				</File>
7658
			</Filter>
7666
			</Filter>
7659
		</Filter>
7667
		</Filter>
7660
		<Filter
7668
		<Filter
- WebCore/WebCore.xcodeproj/project.pbxproj +8 lines
Lines 3644-3649 WebCore/WebCore.xcodeproj/project.pbxproj_sec1
3644
		BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */; };
3644
		BCA169A30BFD55B40019CA76 /* JSHTMLTableCaptionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */; };
3645
		BCA378160D15C64600B793D6 /* PausedTimeouts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */; };
3645
		BCA378160D15C64600B793D6 /* PausedTimeouts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */; };
3646
		BCA378170D15C64600B793D6 /* PausedTimeouts.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA378150D15C64600B793D6 /* PausedTimeouts.h */; };
3646
		BCA378170D15C64600B793D6 /* PausedTimeouts.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA378150D15C64600B793D6 /* PausedTimeouts.h */; };
3647
		BCA378BC0D15F64200B793D6 /* ScheduledAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */; };
3648
		BCA378BD0D15F64200B793D6 /* ScheduledAction.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA378BB0D15F64200B793D6 /* ScheduledAction.h */; };
3647
		BCA85A100C3AEAF4006F8308 /* DOMSVGNumberInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */; };
3649
		BCA85A100C3AEAF4006F8308 /* DOMSVGNumberInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */; };
3648
		BCAA90C30A7EBA60008B1229 /* ScrollBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */; };
3650
		BCAA90C30A7EBA60008B1229 /* ScrollBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */; };
3649
		BCB16B8B0979B01400467741 /* DeprecatedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB16B880979B01400467741 /* DeprecatedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
3651
		BCB16B8B0979B01400467741 /* DeprecatedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB16B880979B01400467741 /* DeprecatedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
Lines 7655-7660 WebCore/WebCore.xcodeproj/project.pbxproj_sec2
7655
		BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLTableCaptionElement.h; sourceTree = "<group>"; };
7657
		BCA169A10BFD55B40019CA76 /* JSHTMLTableCaptionElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLTableCaptionElement.h; sourceTree = "<group>"; };
7656
		BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PausedTimeouts.cpp; sourceTree = "<group>"; };
7658
		BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PausedTimeouts.cpp; sourceTree = "<group>"; };
7657
		BCA378150D15C64600B793D6 /* PausedTimeouts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PausedTimeouts.h; sourceTree = "<group>"; };
7659
		BCA378150D15C64600B793D6 /* PausedTimeouts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PausedTimeouts.h; sourceTree = "<group>"; };
7660
		BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScheduledAction.cpp; sourceTree = "<group>"; };
7661
		BCA378BB0D15F64200B793D6 /* ScheduledAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScheduledAction.h; sourceTree = "<group>"; };
7658
		BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMSVGNumberInternal.h; sourceTree = "<group>"; };
7662
		BCA85A0F0C3AEAF4006F8308 /* DOMSVGNumberInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOMSVGNumberInternal.h; sourceTree = "<group>"; };
7659
		BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScrollBar.cpp; path = platform/ScrollBar.cpp; sourceTree = SOURCE_ROOT; };
7663
		BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScrollBar.cpp; path = platform/ScrollBar.cpp; sourceTree = SOURCE_ROOT; };
7660
		BCB16B880979B01400467741 /* DeprecatedArray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DeprecatedArray.h; sourceTree = "<group>"; };
7664
		BCB16B880979B01400467741 /* DeprecatedArray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DeprecatedArray.h; sourceTree = "<group>"; };
Lines 11410-11415 WebCore/WebCore.xcodeproj/project.pbxproj_sec3
11410
				93B70D5A09EB0C7C009D8468 /* kjs_window.h */,
11414
				93B70D5A09EB0C7C009D8468 /* kjs_window.h */,
11411
				BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */,
11415
				BCA378140D15C64600B793D6 /* PausedTimeouts.cpp */,
11412
				BCA378150D15C64600B793D6 /* PausedTimeouts.h */,
11416
				BCA378150D15C64600B793D6 /* PausedTimeouts.h */,
11417
				BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */,
11418
				BCA378BB0D15F64200B793D6 /* ScheduledAction.h */,
11413
			);
11419
			);
11414
			path = js;
11420
			path = js;
11415
			sourceTree = "<group>";
11421
			sourceTree = "<group>";
Lines 14107-14112 WebCore/WebCore.xcodeproj/project.pbxproj_sec4
14107
				BC4BF9E50D11E133007D247F /* ClassNames.h in Headers */,
14113
				BC4BF9E50D11E133007D247F /* ClassNames.h in Headers */,
14108
				B28BC31A0D135E5400CDBA27 /* JSEventTargetBase.lut.h in Headers */,
14114
				B28BC31A0D135E5400CDBA27 /* JSEventTargetBase.lut.h in Headers */,
14109
				BCA378170D15C64600B793D6 /* PausedTimeouts.h in Headers */,
14115
				BCA378170D15C64600B793D6 /* PausedTimeouts.h in Headers */,
14116
				BCA378BD0D15F64200B793D6 /* ScheduledAction.h in Headers */,
14110
			);
14117
			);
14111
			runOnlyForDeploymentPostprocessing = 0;
14118
			runOnlyForDeploymentPostprocessing = 0;
14112
		};
14119
		};
Lines 15820-15825 WebCore/WebCore.xcodeproj/project.pbxproj_sec5
15820
				BC904B760D10998F00680D32 /* ClassNodeList.cpp in Sources */,
15827
				BC904B760D10998F00680D32 /* ClassNodeList.cpp in Sources */,
15821
				BC4BF9E40D11E133007D247F /* ClassNames.cpp in Sources */,
15828
				BC4BF9E40D11E133007D247F /* ClassNames.cpp in Sources */,
15822
				BCA378160D15C64600B793D6 /* PausedTimeouts.cpp in Sources */,
15829
				BCA378160D15C64600B793D6 /* PausedTimeouts.cpp in Sources */,
15830
				BCA378BC0D15F64200B793D6 /* ScheduledAction.cpp in Sources */,
15823
			);
15831
			);
15824
			runOnlyForDeploymentPostprocessing = 0;
15832
			runOnlyForDeploymentPostprocessing = 0;
15825
		};
15833
		};
- WebCore/bindings/js/PausedTimeouts.cpp -1 / +1 lines
Lines 23-29 WebCore/bindings/js/PausedTimeouts.cpp_sec1
23
#include "config.h"
23
#include "config.h"
24
#include "PausedTimeouts.h"
24
#include "PausedTimeouts.h"
25
25
26
#include "kjs_window.h"
26
#include "ScheduledAction.h"
27
27
28
namespace WebCore {
28
namespace WebCore {
29
29
- WebCore/bindings/js/PausedTimeouts.h -5 / +3 lines
Lines 22-39 WebCore/bindings/js/PausedTimeouts.h_sec1
22
22
23
#include <wtf/Noncopyable.h>
23
#include <wtf/Noncopyable.h>
24
24
25
namespace KJS {
26
    class ScheduledAction;
27
}
28
29
namespace WebCore {
25
namespace WebCore {
30
26
27
    class ScheduledAction;
28
31
    struct PausedTimeout {
29
    struct PausedTimeout {
32
        int timeoutId;
30
        int timeoutId;
33
        int nestingLevel;
31
        int nestingLevel;
34
        double nextFireInterval;
32
        double nextFireInterval;
35
        double repeatInterval;
33
        double repeatInterval;
36
        KJS::ScheduledAction* action;
34
        ScheduledAction* action;
37
    };
35
    };
38
36
39
    class PausedTimeouts : Noncopyable {
37
    class PausedTimeouts : Noncopyable {
- WebCore/bindings/js/ScheduledAction.cpp +1680 lines
Line 0 WebCore/bindings/js/ScheduledAction.cpp_sec1
1
// -*- c-basic-offset: 4 -*-
2
/*
3
 *  Copyright (C) 2000 Harri Porten (porten@kde.org)
4
 *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
5
 *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reseved.
6
 *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
7
 *
8
 *  This library is free software; you can redistribute it and/or
9
 *  modify it under the terms of the GNU Lesser General Public
10
 *  License as published by the Free Software Foundation; either
11
 *  version 2 of the License, or (at your option) any later version.
12
 *
13
 *  This library is distributed in the hope that it will be useful,
14
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 *  Lesser General Public License for more details.
17
 *
18
 *  You should have received a copy of the GNU Lesser General Public
19
 *  License along with this library; if not, write to the Free Software
20
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
21
 *  USA
22
 */
23
24
#include "config.h"
25
#include "kjs_window.h"
26
27
#include "Base64.h"
28
#include "CString.h"
29
#include "Chrome.h"
30
#include "DOMWindow.h"
31
#include "Element.h"
32
#include "EventListener.h"
33
#include "EventNames.h"
34
#include "ExceptionCode.h"
35
#include "FloatRect.h"
36
#include "Frame.h"
37
#include "FrameLoadRequest.h"
38
#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
#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
#include "kjs_proxy.h"
63
#include <wtf/MathExtras.h>
64
65
#if ENABLE(XSLT)
66
#include "JSXSLTProcessor.h"
67
#endif
68
69
using namespace WebCore;
70
using namespace EventNames;
71
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)
206
{
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);
213
}
214
215
Window::~Window()
216
{
217
    clearAllTimeouts();
218
219
    // Clear any backpointers to the window
220
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 window
262
}
263
264
Location* Window::location() const
265
{
266
    if (!d->loc)
267
        d->loc = new Location(impl()->frame());
268
    return d->loc;
269
}
270
271
// reference our special objects during garbage collection
272
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 value
305
            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 we
330
    // know what URL we are going to open. Unfortunately, this code passes the empty string
331
    // 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 currently
333
    // 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 settings
391
    // - 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 print
394
    // - 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 MacIE
404
    wargs.widthSet = true;
405
    wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
406
    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's
440
    // 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) const
456
{
457
   ASSERT(impl()->frame());
458
459
   switch (token) {
460
   case Crypto:
461
      return jsUndefined(); // FIXME: implement this
462
   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 fail
481
      // 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 every
490
      // time
491
      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
#else
504
      return jsUndefined();
505
#endif
506
#if ENABLE(XSLT)
507
    case XSLTProcessor_:
508
      if (!allowsAccessFrom(exec))
509
        return jsUndefined();
510
      return new XSLTProcessorConstructorImp(exec);
511
#else
512
    case XSLTProcessor_:
513
      return jsUndefined();
514
#endif
515
   }
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 to
602
  // match Mozilla. This does not match IE, but some sites end up
603
  // naming frames things that conflict with window properties that
604
  // are in Moz but not IE. Since we have some of these, we have to do
605
  // 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
      else
621
        slot.setUndefined(this);
622
    } else
623
      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.Image1
639
  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 gesture
683
          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) const
797
{
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't
813
    // 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 this
843
    // frame does not destroy it
844
    ASSERT(impl()->frame());
845
    impl()->frame()->keepAlive();
846
    return JSGlobalObject::globalExec();
847
}
848
849
bool Window::shouldInterruptScript() const
850
{
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 NULL
855
    // in this case, but if it is, we've gotten into a state where we may have
856
    // 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 solutions
859
    // 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) const
878
{
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 list
910
    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 been
953
  // disconnected yet
954
  if (Frame* frame = impl()->frame())
955
    frame->scriptProxy()->globalObject()->reset(JSDOMWindowPrototype::self());
956
957
  // there's likely to be lots of garbage now
958
  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 those
1051
    // 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() helper
1077
    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 object
1092
}
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
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
    } else
1248
        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 works
1253
    // for all possible entry points that might possibly execute script, but this seems
1254
    // to be a bit too low-level.
1255
    if (Document* doc = frame->document())
1256
        doc->updateRendering();
1257
1258
    scriptProxy->setProcessingTimerCallback(false);
1259
}
1260
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 us
1274
    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've
1282
    // 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
    else
1290
        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 to
1357
    // even look up since they are the empty and deleted value
1358
    // respectively
1359
    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 12
1422
  assign        &LocationProtoFuncAssign::create        DontDelete|Function 1
1423
  hash          Location::Hash                          DontDelete
1424
  host          Location::Host                          DontDelete
1425
  hostname      Location::Hostname                      DontDelete
1426
  href          Location::Href                          DontDelete
1427
  pathname      Location::Pathname                      DontDelete
1428
  port          Location::Port                          DontDelete
1429
  protocol      Location::Protocol                      DontDelete
1430
  search        Location::Search                        DontDelete
1431
  toString      &LocationProtoFuncToString::create      DontEnum|DontDelete|Function 0
1432
  replace       &LocationProtoFuncReplace::create       DontDelete|Function 1
1433
  reload        &LocationProtoFuncReload::create        DontDelete|Function 0
1434
@end
1435
*/
1436
1437
Location::Location(Frame* frame)
1438
    : m_frame(frame)
1439
{
1440
}
1441
1442
JSValue *Location::getValueProperty(ExecState* exec, int token) const
1443
{
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 says
1450
    // "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::create
1486
                                                   && entry->value.functionValue != &LocationProtoFuncReload::create
1487
                                                   && 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 inadvertently
1512
      // 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 gesture
1633
            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 KJS
1665
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
} // namespace WebCore
- WebCore/bindings/js/ScheduledAction.cpp -1590 / +11 lines
Lines 1-4 WebCore/bindings/js/ScheduledAction.cpp_sec1
1
// -*- c-basic-offset: 4 -*-
2
/*
1
/*
3
 *  Copyright (C) 2000 Harri Porten (porten@kde.org)
2
 *  Copyright (C) 2000 Harri Porten (porten@kde.org)
4
 *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
3
 *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
Lines 22-1208 WebCore/bindings/js/ScheduledAction.cpp_sec2
22
 */
21
 */
23
22
24
#include "config.h"
23
#include "config.h"
25
#include "kjs_window.h"
24
#include "ScheduledAction.h"
26
25
27
#include "Base64.h"
28
#include "CString.h"
29
#include "Chrome.h"
26
#include "Chrome.h"
27
#include "CString.h"
30
#include "DOMWindow.h"
28
#include "DOMWindow.h"
31
#include "Element.h"
32
#include "EventListener.h"
33
#include "EventNames.h"
34
#include "ExceptionCode.h"
35
#include "FloatRect.h"
36
#include "Frame.h"
29
#include "Frame.h"
37
#include "FrameLoadRequest.h"
38
#include "FrameLoader.h"
30
#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
#include "Page.h"
31
#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
#include "kjs_proxy.h"
32
#include "kjs_proxy.h"
63
#include <wtf/MathExtras.h>
33
#include "kjs_window.h"
64
65
#if ENABLE(XSLT)
66
#include "JSXSLTProcessor.h"
67
#endif
68
69
using namespace WebCore;
70
using namespace EventNames;
71
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)
206
{
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);
213
}
214
215
Window::~Window()
216
{
217
    clearAllTimeouts();
218
219
    // Clear any backpointers to the window
220
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 window
262
}
263
264
Location* Window::location() const
265
{
266
    if (!d->loc)
267
        d->loc = new Location(impl()->frame());
268
    return d->loc;
269
}
270
271
// reference our special objects during garbage collection
272
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 value
305
            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 we
330
    // know what URL we are going to open. Unfortunately, this code passes the empty string
331
    // 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 currently
333
    // 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 settings
391
    // - 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 print
394
    // - 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 MacIE
404
    wargs.widthSet = true;
405
    wargs.height = WindowFeatures::floatFeature(features, "dialogheight", 100, screenRect.height(), 450); // default here came from frame size of dialog in MacIE
406
    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's
440
    // 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) const
456
{
457
   ASSERT(impl()->frame());
458
459
   switch (token) {
460
   case Crypto:
461
      return jsUndefined(); // FIXME: implement this
462
   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 fail
481
      // 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 every
490
      // time
491
      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
#else
504
      return jsUndefined();
505
#endif
506
#if ENABLE(XSLT)
507
    case XSLTProcessor_:
508
      if (!allowsAccessFrom(exec))
509
        return jsUndefined();
510
      return new XSLTProcessorConstructorImp(exec);
511
#else
512
    case XSLTProcessor_:
513
      return jsUndefined();
514
#endif
515
   }
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 to
602
  // match Mozilla. This does not match IE, but some sites end up
603
  // naming frames things that conflict with window properties that
604
  // are in Moz but not IE. Since we have some of these, we have to do
605
  // 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
      else
621
        slot.setUndefined(this);
622
    } else
623
      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.Image1
639
  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 gesture
683
          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) const
797
{
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't
813
    // 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 this
843
    // frame does not destroy it
844
    ASSERT(impl()->frame());
845
    impl()->frame()->keepAlive();
846
    return JSGlobalObject::globalExec();
847
}
848
849
bool Window::shouldInterruptScript() const
850
{
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 NULL
855
    // in this case, but if it is, we've gotten into a state where we may have
856
    // 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 solutions
859
    // 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) const
878
{
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 list
910
    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 been
953
  // disconnected yet
954
  if (Frame* frame = impl()->frame())
955
    frame->scriptProxy()->globalObject()->reset(JSDOMWindowPrototype::self());
956
957
  // there's likely to be lots of garbage now
958
  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 those
1051
    // 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() helper
1077
    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 object
1092
}
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
34
1192
JSValue* WindowProtoFuncNotImplemented::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
35
using namespace KJS;
1193
{
1194
    if (!thisObj->inherits(&Window::info))
1195
        return throwError(exec, TypeError);
1196
36
1197
    return jsUndefined();
37
namespace WebCore {
1198
}
1199
38
1200
void Window::setReturnValueSlot(JSValue** slot)
39
ScheduledAction::ScheduledAction(JSValue* func, const List& args)
40
    : m_func(func)
1201
{
41
{
1202
    d->m_returnValueSlot = slot;
42
    List::const_iterator end = args.end();
43
    for (List::const_iterator it = args.begin(); it != end; ++it)
44
        m_args.append(*it);
1203
}
45
}
1204
46
1205
////////////////////// ScheduledAction ////////////////////////
1206
47
1207
void ScheduledAction::execute(Window* window)
48
void ScheduledAction::execute(Window* window)
1208
{
49
{
Lines 1226-1234 void ScheduledAction::execute(Window* wi WebCore/bindings/js/ScheduledAction.cpp_sec3
1226
67
1227
            List args;
68
            List args;
1228
            size_t size = m_args.size();
69
            size_t size = m_args.size();
1229
            for (size_t i = 0; i < size; ++i) {
70
            for (size_t i = 0; i < size; ++i)
1230
                args.append(m_args[i]);
71
                args.append(m_args[i]);
1231
            }
1232
72
1233
            globalObject->startTimeoutCheck();
73
            globalObject->startTimeoutCheck();
1234
            static_cast<JSObject*>(func)->call(exec, window, args);
74
            static_cast<JSObject*>(func)->call(exec, window, args);
Lines 1258-1680 void ScheduledAction::execute(Window* wi WebCore/bindings/js/ScheduledAction.cpp_sec4
1258
    scriptProxy->setProcessingTimerCallback(false);
98
    scriptProxy->setProcessingTimerCallback(false);
1259
}
99
}
1260
100
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 us
1274
    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've
1282
    // 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
    else
1290
        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 to
1357
    // even look up since they are the empty and deleted value
1358
    // respectively
1359
    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 12
1422
  assign        &LocationProtoFuncAssign::create        DontDelete|Function 1
1423
  hash          Location::Hash                          DontDelete
1424
  host          Location::Host                          DontDelete
1425
  hostname      Location::Hostname                      DontDelete
1426
  href          Location::Href                          DontDelete
1427
  pathname      Location::Pathname                      DontDelete
1428
  port          Location::Port                          DontDelete
1429
  protocol      Location::Protocol                      DontDelete
1430
  search        Location::Search                        DontDelete
1431
  toString      &LocationProtoFuncToString::create      DontEnum|DontDelete|Function 0
1432
  replace       &LocationProtoFuncReplace::create       DontDelete|Function 1
1433
  reload        &LocationProtoFuncReload::create        DontDelete|Function 0
1434
@end
1435
*/
1436
1437
Location::Location(Frame* frame)
1438
    : m_frame(frame)
1439
{
1440
}
1441
1442
JSValue *Location::getValueProperty(ExecState* exec, int token) const
1443
{
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 says
1450
    // "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::create
1486
                                                   && entry->value.functionValue != &LocationProtoFuncReload::create
1487
                                                   && 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 inadvertently
1512
      // 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 gesture
1633
            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 KJS
1665
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
} // namespace WebCore
101
} // namespace WebCore
- WebCore/bindings/js/ScheduledAction.h +237 lines
Line 0 WebCore/bindings/js/ScheduledAction.h_sec1
1
/*
2
 *  Copyright (C) 2000 Harri Porten (porten@kde.org)
3
 *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reseved.
4
 *
5
 *  This library is free software; you can redistribute it and/or
6
 *  modify it under the terms of the GNU Lesser General Public
7
 *  License as published by the Free Software Foundation; either
8
 *  version 2 of the License, or (at your option) any later version.
9
 *
10
 *  This library is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 *  Lesser General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU Lesser General Public
16
 *  License along with this library; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
19
20
#ifndef kjs_window_h
21
#define kjs_window_h
22
23
#include "PlatformString.h"
24
#include "kjs_binding.h"
25
#include <kjs/protect.h>
26
#include <wtf/HashMap.h>
27
#include <wtf/Noncopyable.h>
28
#include <wtf/OwnPtr.h>
29
30
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 DOMObject
49
  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 Window
63
    // for the specified frame p this will be returned in order to have unique
64
    // bindings.
65
    static JSValue* retrieve(WebCore::Frame*);
66
67
    // Returns the Window object for a given HTML frame
68
    static Window* retrieveWindow(WebCore::Frame*);
69
70
    // Returns a pointer to the Window object this javascript interpreting instance 
71
    // 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
        // Attributes
130
        Crypto, Event_, Location_, Navigator_,
131
        ClientInformation,
132
133
        // Event Listeners
134
        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
        // Constructors
143
        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_CLASS
178
179
180
  /**
181
   * An action (either function or string) to be executed after a specified
182
   * 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
  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_CLASS
230
231
} // namespace KJS
232
233
namespace WebCore {
234
    KJS::JSValue* toJS(KJS::ExecState*, DOMWindow*);
235
} // namespace WebCore
236
237
#endif // kjs_window_h
- WebCore/bindings/js/ScheduledAction.h -193 / +14 lines
Lines 17-181 WebCore/bindings/js/ScheduledAction.h_sec1
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
18
 */
19
19
20
#ifndef kjs_window_h
20
#ifndef ScheduledAction_h
21
#define kjs_window_h
21
#define ScheduledAction_h
22
22
23
#include "PlatformString.h"
23
#include "PlatformString.h"
24
#include "kjs_binding.h"
25
#include <kjs/protect.h>
24
#include <kjs/protect.h>
26
#include <wtf/HashMap.h>
25
#include <wtf/Vector.h>
27
#include <wtf/Noncopyable.h>
28
#include <wtf/OwnPtr.h>
29
30
namespace WebCore {
31
    class AtomicString;
32
    class DOMWindow;
33
    class Frame;
34
    class JSEventListener;
35
    class JSUnprotectedEventListener;
36
    class PausedTimeouts;
37
}
38
26
39
namespace KJS {
27
namespace KJS {
40
41
    class DOMWindowTimer;
42
    class Location;
43
    class ScheduledAction;
44
    class Window;
28
    class Window;
45
    class WindowFunc;
29
    class JSValue;
46
    class WindowPrivate;
30
    class List;
47
31
}
48
  // This is the only WebCore JS binding which does not inherit from DOMObject
49
  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 Window
63
    // for the specified frame p this will be returned in order to have unique
64
    // bindings.
65
    static JSValue* retrieve(WebCore::Frame*);
66
67
    // Returns the Window object for a given HTML frame
68
    static Window* retrieveWindow(WebCore::Frame*);
69
70
    // Returns a pointer to the Window object this javascript interpreting instance 
71
    // 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
        // Attributes
130
        Crypto, Event_, Location_, Navigator_,
131
        ClientInformation,
132
133
        // Event Listeners
134
        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
        // Constructors
143
        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_CLASS
178
32
33
namespace WebCore {
179
34
180
  /**
35
  /**
181
   * An action (either function or string) to be executed after a specified
36
   * An action (either function or string) to be executed after a specified
Lines 184-237 FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_F WebCore/bindings/js/ScheduledAction.h_sec2
184
   */
39
   */
185
    class ScheduledAction {
40
    class ScheduledAction {
186
    public:
41
    public:
187
        ScheduledAction(JSValue* func, const List& args);
42
        ScheduledAction(KJS::JSValue* func, const KJS::List& args);
188
        ScheduledAction(const WebCore::String& code)
43
        ScheduledAction(const String& code)
189
            : m_code(code)
44
            : m_code(code)
190
        {
45
        {
191
        }
46
        }
192
47
193
        void execute(Window *);
48
        void execute(KJS::Window*);
194
49
195
    private:
50
    private:
196
        ProtectedPtr<JSValue> m_func;
51
        KJS::ProtectedPtr<KJS::JSValue> m_func;
197
        Vector<ProtectedPtr<JSValue> > m_args;
52
        Vector<KJS::ProtectedPtr<KJS::JSValue> > m_args;
198
        WebCore::String m_code;
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_CLASS
230
231
} // namespace KJS
232
233
namespace WebCore {
234
    KJS::JSValue* toJS(KJS::ExecState*, DOMWindow*);
235
} // namespace WebCore
56
} // namespace WebCore
236
57
237
#endif // kjs_window_h
58
#endif // ScheduledAction_h
- WebCore/bindings/js/kjs_window.cpp -72 / +9 lines
Lines 52-57 WebCore/bindings/js/kjs_window.cpp_sec1
52
#include "PlatformScreen.h"
52
#include "PlatformScreen.h"
53
#include "PlugInInfoStore.h"
53
#include "PlugInInfoStore.h"
54
#include "RenderView.h"
54
#include "RenderView.h"
55
#include "ScheduledAction.h"
55
#include "SecurityOrigin.h"
56
#include "SecurityOrigin.h"
56
#include "Settings.h"
57
#include "Settings.h"
57
#include "WindowFeatures.h"
58
#include "WindowFeatures.h"
Lines 99-105 struct WindowPrivate { WebCore/bindings/js/kjs_window.cpp_sec2
99
100
100
class DOMWindowTimer : public TimerBase {
101
class DOMWindowTimer : public TimerBase {
101
public:
102
public:
102
    DOMWindowTimer(int timeoutId, int nestingLevel, Window* object, ScheduledAction* action)
103
    DOMWindowTimer(int timeoutId, int nestingLevel, Window* object, WebCore::ScheduledAction* action)
103
        : m_timeoutId(timeoutId)
104
        : m_timeoutId(timeoutId)
104
        , m_nestingLevel(nestingLevel)
105
        , m_nestingLevel(nestingLevel)
105
        , m_object(object)
106
        , m_object(object)
Lines 118-125 public: WebCore/bindings/js/kjs_window.cpp_sec3
118
    int nestingLevel() const { return m_nestingLevel; }
119
    int nestingLevel() const { return m_nestingLevel; }
119
    void setNestingLevel(int n) { m_nestingLevel = n; }
120
    void setNestingLevel(int n) { m_nestingLevel = n; }
120
121
121
    ScheduledAction* action() const { return m_action; }
122
    WebCore::ScheduledAction* action() const { return m_action; }
122
    ScheduledAction* takeAction() { ScheduledAction* a = m_action; m_action = 0; return a; }
123
    WebCore::ScheduledAction* takeAction() { WebCore::ScheduledAction* a = m_action; m_action = 0; return a; }
123
124
124
private:
125
private:
125
    virtual void fired();
126
    virtual void fired();
Lines 127-133 private: WebCore/bindings/js/kjs_window.cpp_sec4
127
    int m_timeoutId;
128
    int m_timeoutId;
128
    int m_nestingLevel;
129
    int m_nestingLevel;
129
    Window* m_object;
130
    Window* m_object;
130
    ScheduledAction* m_action;
131
    WebCore::ScheduledAction* m_action;
131
};
132
};
132
133
133
} // namespace KJS
134
} // namespace KJS
Lines 1202-1263 void Window::setReturnValueSlot(JSValue* WebCore/bindings/js/kjs_window.cpp_sec5
1202
    d->m_returnValueSlot = slot;
1203
    d->m_returnValueSlot = slot;
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
    } else
1248
        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 works
1253
    // for all possible entry points that might possibly execute script, but this seems
1254
    // to be a bit too low-level.
1255
    if (Document* doc = frame->document())
1256
        doc->updateRendering();
1257
1258
    scriptProxy->setProcessingTimerCallback(false);
1259
}
1260
1261
////////////////////// timeouts ////////////////////////
1206
////////////////////// timeouts ////////////////////////
1262
1207
1263
void Window::clearAllTimeouts()
1208
void Window::clearAllTimeouts()
Lines 1266-1272 void Window::clearAllTimeouts() WebCore/bindings/js/kjs_window.cpp_sec6
1266
    d->m_timeouts.clear();
1211
    d->m_timeouts.clear();
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
    int timeoutId = ++lastUsedTimeoutId;
1216
    int timeoutId = ++lastUsedTimeoutId;
1272
1217
Lines 1291-1312 int Window::installTimeout(ScheduledActi WebCore/bindings/js/kjs_window.cpp_sec7
1291
    return timeoutId;
1236
    return timeoutId;
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
int Window::installTimeout(const UString& handler, int t, bool singleShot)
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
int Window::installTimeout(JSValue* func, const List& args, int t, bool singleShot)
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
1312
WebCore::PausedTimeouts* Window::pauseTimeouts()
1249
WebCore::PausedTimeouts* Window::pauseTimeouts()
Lines 1378-1384 void Window::timerFired(DOMWindowTimer* WebCore/bindings/js/kjs_window.cpp_sec8
1378
    }
1315
    }
1379
1316
1380
    // Delete timer before executing the action for one-shot timers.
1317
    // Delete timer before executing the action for one-shot timers.
1381
    ScheduledAction* action = timer->takeAction();
1318
    WebCore::ScheduledAction* action = timer->takeAction();
1382
    d->m_timeouts.remove(timer->timeoutId());
1319
    d->m_timeouts.remove(timer->timeoutId());
1383
    delete timer;
1320
    delete timer;
1384
    action->execute(this);
1321
    action->execute(this);
- WebCore/bindings/js/kjs_window.h -24 / +3 lines
Lines 34-46 namespace WebCore { WebCore/bindings/js/kjs_window.h_sec1
34
    class JSEventListener;
34
    class JSEventListener;
35
    class JSUnprotectedEventListener;
35
    class JSUnprotectedEventListener;
36
    class PausedTimeouts;
36
    class PausedTimeouts;
37
    class ScheduledAction;
37
}
38
}
38
39
39
namespace KJS {
40
namespace KJS {
40
41
41
    class DOMWindowTimer;
42
    class DOMWindowTimer;
42
    class Location;
43
    class Location;
43
    class ScheduledAction;
44
    class Window;
44
    class Window;
45
    class WindowFunc;
45
    class WindowFunc;
46
    class WindowPrivate;
46
    class WindowPrivate;
Lines 48-54 namespace KJS { WebCore/bindings/js/kjs_window.h_sec2
48
  // This is the only WebCore JS binding which does not inherit from DOMObject
48
  // This is the only WebCore JS binding which does not inherit from DOMObject
49
  class Window : public JSGlobalObject {
49
  class Window : public JSGlobalObject {
50
    friend class Location;
50
    friend class Location;
51
    friend class ScheduledAction;
51
    friend class WebCore::ScheduledAction;
52
  protected:
52
  protected:
53
    Window(WebCore::DOMWindow*);
53
    Window(WebCore::DOMWindow*);
54
54
Lines 155-161 namespace KJS { WebCore/bindings/js/kjs_window.h_sec3
155
155
156
    void clearHelperObjectProperties();
156
    void clearHelperObjectProperties();
157
    void clearAllTimeouts();
157
    void clearAllTimeouts();
158
    int installTimeout(ScheduledAction*, int interval, bool singleShot);
158
    int installTimeout(WebCore::ScheduledAction*, int interval, bool singleShot);
159
159
160
    RefPtr<WebCore::DOMWindow> m_impl;
160
    RefPtr<WebCore::DOMWindow> m_impl;
161
    OwnPtr<WindowPrivate> d;
161
    OwnPtr<WindowPrivate> d;
Lines 177-203 FOR_EACH_CLASS(KJS_IMPLEMENT_PROTOTYPE_F WebCore/bindings/js/kjs_window.h_sec4
177
#undef FOR_EACH_CLASS
177
#undef FOR_EACH_CLASS
178
178
179
179
180
  /**
181
   * An action (either function or string) to be executed after a specified
182
   * 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
  class Location : public DOMObject {
180
  class Location : public DOMObject {
202
    friend class Window;
181
    friend class Window;
203
  public:
182
  public:

Return to Bug 16385