OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2000 Harri Porten (porten@kde.org) | 2 * Copyright (C) 2000 Harri Porten (porten@kde.org) |
3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) | 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) |
4 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. | 4 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. |
5 * Copyright (C) 2006 James G. Speth (speth@end.com) | 5 * Copyright (C) 2006 James G. Speth (speth@end.com) |
6 * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) | 6 * Copyright (C) 2006 Samuel Weinig (sam@webkit.org) |
7 * Copyright (C) 2007, 2008 Google Inc. All Rights Reserved. | 7 * Copyright (C) 2007, 2008 Google Inc. All Rights Reserved. |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Lesser General Public | 10 * modify it under the terms of the GNU Lesser General Public |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 #include "CanvasGradient.h" | 49 #include "CanvasGradient.h" |
50 #include "CanvasPattern.h" | 50 #include "CanvasPattern.h" |
51 #include "CanvasRenderingContext2D.h" | 51 #include "CanvasRenderingContext2D.h" |
52 #include "CanvasStyle.h" | 52 #include "CanvasStyle.h" |
53 #include "Clipboard.h" | 53 #include "Clipboard.h" |
54 #include "ClipboardEvent.h" | 54 #include "ClipboardEvent.h" |
55 #include "Console.h" | 55 #include "Console.h" |
56 #include "DOMParser.h" | 56 #include "DOMParser.h" |
57 #include "DOMStringList.h" | 57 #include "DOMStringList.h" |
58 #include "DOMTimer.h" | 58 #include "DOMTimer.h" |
59 #include "DOMWindow.h" | |
60 #include "Document.h" | 59 #include "Document.h" |
61 #include "DocumentFragment.h" | 60 #include "DocumentFragment.h" |
62 #include "Event.h" | 61 #include "Event.h" |
63 #include "EventTarget.h" | 62 #include "EventTarget.h" |
64 #include "FloatRect.h" | 63 #include "FloatRect.h" |
65 #include "Frame.h" | 64 #include "Frame.h" |
66 #include "FrameLoader.h" | 65 #include "FrameLoader.h" |
67 #include "FrameTree.h" | 66 #include "FrameTree.h" |
68 #include "HTMLBodyElement.h" | 67 #include "HTMLBodyElement.h" |
69 #include "HTMLCanvasElement.h" | 68 #include "HTMLCanvasElement.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 // Generate a wrapper. | 134 // Generate a wrapper. |
136 Document* doc = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); | 135 Document* doc = V8Proxy::DOMWrapperToNative<Document>(info.Holder()); |
137 v8::Handle<v8::Value> wrapper = | 136 v8::Handle<v8::Value> wrapper = |
138 V8Proxy::DOMImplementationToV8Object(doc->implementation()); | 137 V8Proxy::DOMImplementationToV8Object(doc->implementation()); |
139 // Store the wrapper in the internal field. | 138 // Store the wrapper in the internal field. |
140 info.Holder()->SetInternalField(kDocumentImplementationIndex, wrapper); | 139 info.Holder()->SetInternalField(kDocumentImplementationIndex, wrapper); |
141 | 140 |
142 return wrapper; | 141 return wrapper; |
143 } | 142 } |
144 | 143 |
145 // TODO(mbelshe): This should move into V8DOMWindowCustom.cpp | |
146 // Can't move it right now because it depends on V8ScheduledAction, | |
147 // which is private to this file (v8_custom.cpp). | |
148 v8::Handle<v8::Value> V8Custom::WindowSetTimeoutImpl(const v8::Arguments& args, | |
149 bool single_shot) { | |
150 int num_arguments = args.Length(); | |
151 | |
152 if (num_arguments < 1) return v8::Undefined(); | |
153 | |
154 DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( | |
155 V8ClassIndex::DOMWINDOW, args.Holder()); | |
156 | |
157 if (!imp->frame()) | |
158 return v8::Undefined(); | |
159 | |
160 if (!V8Proxy::CanAccessFrame(imp->frame(), true)) | |
161 return v8::Undefined(); | |
162 | |
163 ScriptExecutionContext* script_context = | |
164 static_cast<ScriptExecutionContext*>(imp->frame()->document()); | |
165 | |
166 v8::Handle<v8::Value> function = args[0]; | |
167 | |
168 int32_t timeout = 0; | |
169 if (num_arguments >= 2) timeout = args[1]->Int32Value(); | |
170 | |
171 int id; | |
172 if (function->IsString()) { | |
173 // Don't allow setting timeouts to run empty functions! | |
174 // (Bug 1009597) | |
175 WebCore::String string_function = ToWebCoreString(function); | |
176 if (string_function.length() == 0) | |
177 return v8::Undefined(); | |
178 | |
179 id = DOMTimer::install(script_context, | |
180 new ScheduledAction(string_function), timeout, | |
181 single_shot); | |
182 } else if (function->IsFunction()) { | |
183 int param_count = num_arguments >= 2 ? num_arguments - 2 : 0; | |
184 v8::Local<v8::Value>* params = 0; | |
185 if (param_count > 0) { | |
186 params = new v8::Local<v8::Value>[param_count]; | |
187 for (int i = 0; i < param_count; i++) | |
188 // parameters must be globalized | |
189 params[i] = args[i+2]; | |
190 } | |
191 | |
192 // params is passed to action, and released in action's destructor | |
193 ScheduledAction* action = new ScheduledAction( | |
194 v8::Handle<v8::Function>::Cast(function), param_count, params); | |
195 | |
196 delete[] params; | |
197 | |
198 id = DOMTimer::install(script_context, action, timeout, single_shot); | |
199 } else { | |
200 // TODO(fqian): what's the right return value if failed. | |
201 return v8::Undefined(); | |
202 } | |
203 return v8::Integer::New(id); | |
204 } | |
205 | |
206 | |
207 // DOMWindow ------------------------------------------------------------------- | |
208 | |
209 static bool IsAscii(const String& str) { | |
210 for (size_t i = 0; i < str.length(); i++) { | |
211 if (str[i] > 0xFF) | |
212 return false; | |
213 } | |
214 return true; | |
215 } | |
216 | |
217 static v8::Handle<v8::Value> Base64Convert(const String& str, bool encode) { | |
218 if (!IsAscii(str)) { | |
219 V8Proxy::SetDOMException(INVALID_CHARACTER_ERR); | |
220 return v8::Handle<v8::Value>(); | |
221 } | |
222 | |
223 Vector<char> in(str.length()); | |
224 for (size_t i = 0; i < str.length(); i++) { | |
225 in[i] = static_cast<char>(str[i]); | |
226 } | |
227 Vector<char> out; | |
228 | |
229 if (encode) { | |
230 base64Encode(in, out); | |
231 } else { | |
232 if (!base64Decode(in, out)) { | |
233 V8Proxy::ThrowError(V8Proxy::GENERAL_ERROR, "Cannot decode base64"); | |
234 return v8::Undefined(); | |
235 } | |
236 } | |
237 | |
238 return v8String(String(out.data(), out.size())); | |
239 } | |
240 | |
241 CALLBACK_FUNC_DECL(DOMWindowAtob) { | |
242 INC_STATS("DOM.DOMWindow.atob()"); | |
243 DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( | |
244 V8ClassIndex::DOMWINDOW, args.Holder()); | |
245 | |
246 if (!V8Proxy::CanAccessFrame(imp->frame(), true)) | |
247 return v8::Undefined(); | |
248 | |
249 if (args.Length() < 1) { | |
250 V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); | |
251 return v8::Undefined(); | |
252 } | |
253 | |
254 if (args[0]->IsNull()) return v8String(""); | |
255 | |
256 String str = ToWebCoreString(args[0]); | |
257 return Base64Convert(str, false); | |
258 } | |
259 | |
260 CALLBACK_FUNC_DECL(DOMWindowBtoa) { | |
261 INC_STATS("DOM.DOMWindow.btoa()"); | |
262 DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( | |
263 V8ClassIndex::DOMWINDOW, args.Holder()); | |
264 | |
265 if (!V8Proxy::CanAccessFrame(imp->frame(), true)) | |
266 return v8::Undefined(); | |
267 | |
268 if (args.Length() < 1) { | |
269 V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); | |
270 return v8::Undefined(); | |
271 } | |
272 | |
273 if (args[0]->IsNull()) return v8String(""); | |
274 | |
275 String str = ToWebCoreString(args[0]); | |
276 return Base64Convert(str, true); | |
277 } | |
278 | |
279 // TODO(fqian): returning string is cheating, and we should | |
280 // fix this by calling toString function on the receiver. | |
281 // However, V8 implements toString in JavaScript, which requires | |
282 // switching context of receiver. I consider it is dangerous. | |
283 CALLBACK_FUNC_DECL(DOMWindowToString) | |
284 { | |
285 INC_STATS("DOM.DOMWindow.toString()"); | |
286 return args.This()->ObjectProtoToString(); | |
287 } | |
288 | |
289 CALLBACK_FUNC_DECL(DOMWindowNOP) | |
290 { | |
291 INC_STATS("DOM.DOMWindow.nop()"); | |
292 return v8::Undefined(); | |
293 } | |
294 | |
295 | |
296 static String EventNameFromAttributeName(const String& name) { | |
297 ASSERT(name.startsWith("on")); | |
298 String event_type = name.substring(2); | |
299 | |
300 if (event_type.startsWith("w")) { | |
301 switch(event_type[event_type.length() - 1]) { | |
302 case 't': | |
303 event_type = "webkitAnimationStart"; | |
304 break; | |
305 case 'n': | |
306 event_type = "webkitAnimationIteration"; | |
307 break; | |
308 case 'd': | |
309 ASSERT(event_type.length() > 7); | |
310 if (event_type[7] == 'a') | |
311 event_type = "webkitAnimationEnd"; | |
312 else | |
313 event_type = "webkitTransitionEnd"; | |
314 break; | |
315 } | |
316 } | |
317 | |
318 return event_type; | |
319 } | |
320 | |
321 | |
322 ACCESSOR_SETTER(DOMWindowEventHandler) { | |
323 v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper( | |
324 V8ClassIndex::DOMWINDOW, info.This()); | |
325 if (holder.IsEmpty()) | |
326 return; | |
327 | |
328 DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( | |
329 V8ClassIndex::DOMWINDOW, holder); | |
330 if (!imp->frame()) | |
331 return; | |
332 | |
333 Document* doc = imp->frame()->document(); | |
334 if (!doc) | |
335 return; | |
336 | |
337 String key = ToWebCoreString(name); | |
338 String event_type = EventNameFromAttributeName(key); | |
339 | |
340 if (value->IsNull()) { | |
341 // Clear the event listener | |
342 imp->clearAttributeEventListener(event_type); | |
343 } else { | |
344 V8Proxy* proxy = V8Proxy::retrieve(imp->frame()); | |
345 if (!proxy) | |
346 return; | |
347 | |
348 RefPtr<EventListener> listener = | |
349 proxy->FindOrCreateV8EventListener(value, true); | |
350 if (listener) { | |
351 imp->setAttributeEventListener(event_type, listener); | |
352 } | |
353 } | |
354 } | |
355 | |
356 | |
357 ACCESSOR_GETTER(DOMWindowEventHandler) { | |
358 v8::Handle<v8::Object> holder = V8Proxy::LookupDOMWrapper( | |
359 V8ClassIndex::DOMWINDOW, info.This()); | |
360 if (holder.IsEmpty()) | |
361 return v8::Undefined(); | |
362 | |
363 DOMWindow* imp = V8Proxy::ToNativeObject<DOMWindow>( | |
364 V8ClassIndex::DOMWINDOW, holder); | |
365 if (!imp->frame()) | |
366 return v8::Undefined(); | |
367 | |
368 Document* doc = imp->frame()->document(); | |
369 if (!doc) | |
370 return v8::Undefined(); | |
371 | |
372 String key = ToWebCoreString(name); | |
373 String event_type = EventNameFromAttributeName(key); | |
374 | |
375 EventListener* listener = imp->getAttributeEventListener(event_type); | |
376 return V8Proxy::EventListenerToV8Object(listener); | |
377 } | |
378 | |
379 // --------------- Security Checks ------------------------- | 144 // --------------- Security Checks ------------------------- |
380 NAMED_ACCESS_CHECK(DOMWindow) { | |
381 ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); | |
382 v8::Handle<v8::Value> window = | |
383 V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); | |
384 if (window.IsEmpty()) | |
385 return false; // the frame is gone. | |
386 | |
387 DOMWindow* target_win = | |
388 V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); | |
389 | |
390 ASSERT(target_win); | |
391 | |
392 Frame* target = target_win->frame(); | |
393 if (!target) | |
394 return false; | |
395 | |
396 if (key->IsString()) { | |
397 String name = ToWebCoreString(key); | |
398 | |
399 // Allow access of GET and HAS if index is a subframe. | |
400 if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && | |
401 target->tree()->child(name)) { | |
402 return true; | |
403 } | |
404 } | |
405 | |
406 return V8Proxy::CanAccessFrame(target, false); | |
407 } | |
408 | |
409 | |
410 INDEXED_ACCESS_CHECK(DOMWindow) { | |
411 ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::DOMWINDOW); | |
412 v8::Handle<v8::Value> window = | |
413 V8Proxy::LookupDOMWrapper(V8ClassIndex::DOMWINDOW, host); | |
414 if (window.IsEmpty()) | |
415 return false; | |
416 | |
417 DOMWindow* target_win = | |
418 V8Proxy::ToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, window); | |
419 | |
420 ASSERT(target_win); | |
421 | |
422 Frame* target = target_win->frame(); | |
423 if (!target) | |
424 return false; | |
425 | |
426 // Allow access of GET and HAS if index is a subframe. | |
427 if ((type == v8::ACCESS_GET || type == v8::ACCESS_HAS) && | |
428 target->tree()->child(index)) { | |
429 return true; | |
430 } | |
431 | |
432 return V8Proxy::CanAccessFrame(target, false); | |
433 } | |
434 | |
435 | |
436 INDEXED_ACCESS_CHECK(History) { | 145 INDEXED_ACCESS_CHECK(History) { |
437 ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); | 146 ASSERT(V8ClassIndex::FromInt(data->Int32Value()) == V8ClassIndex::HISTORY); |
438 // Only allow same origin access | 147 // Only allow same origin access |
439 History* imp = | 148 History* imp = |
440 V8Proxy::ToNativeObject<History>(V8ClassIndex::HISTORY, host); | 149 V8Proxy::ToNativeObject<History>(V8ClassIndex::HISTORY, host); |
441 return V8Proxy::CanAccessFrame(imp->frame(), false); | 150 return V8Proxy::CanAccessFrame(imp->frame(), false); |
442 } | 151 } |
443 | 152 |
444 | 153 |
445 NAMED_ACCESS_CHECK(History) { | 154 NAMED_ACCESS_CHECK(History) { |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 #undef MAKE_CASE | 236 #undef MAKE_CASE |
528 | 237 |
529 default: | 238 default: |
530 return V8ClassIndex::INVALID_CLASS_INDEX; | 239 return V8ClassIndex::INVALID_CLASS_INDEX; |
531 } | 240 } |
532 } | 241 } |
533 | 242 |
534 #endif // ENABLE(SVG) | 243 #endif // ENABLE(SVG) |
535 | 244 |
536 } // namespace WebCore | 245 } // namespace WebCore |
OLD | NEW |