1 /*
2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "V8DOMWindow.h"
33
34 #include "Chrome.h"
35 #include "ContentSecurityPolicy.h"
36 #include "DOMTimer.h"
37 #include "DOMWindow.h"
38 #include "ExceptionCode.h"
39 #include "Frame.h"
40 #include "FrameLoadRequest.h"
41 #include "FrameView.h"
42 #include "HTMLCollection.h"
43 #include "HTMLDocument.h"
44 #include "MediaPlayer.h"
45 #include "Page.h"
46 #include "PlatformScreen.h"
47 #include "ScheduledAction.h"
48 #include "ScriptSourceCode.h"
49 #include "SerializedScriptValue.h"
50 #include "Settings.h"
51 #include "SharedWorkerRepository.h"
52 #include "Storage.h"
53 #include "V8Binding.h"
54 #include "V8BindingMacros.h"
55 #include "V8BindingState.h"
56 #include "V8EventListener.h"
57 #include "V8GCForContextDispose.h"
58 #include "V8HiddenPropertyName.h"
59 #include "V8HTMLAudioElementConstructor.h"
60 #include "V8HTMLCollection.h"
61 #include "V8HTMLImageElementConstructor.h"
62 #include "V8HTMLOptionElementConstructor.h"
63 #include "V8MessagePortCustom.h"
64 #include "V8Node.h"
65 #include "V8Proxy.h"
66 #include "V8Utilities.h"
67 #if ENABLE(WEB_SOCKETS)
68 #include "WebSocket.h"
69 #endif
70 #include "WindowFeatures.h"
71
72 namespace WebCore {
73
WindowSetTimeoutImpl(const v8::Arguments & args,bool singleShot)74 v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singleShot)
75 {
76 int argumentCount = args.Length();
77
78 if (argumentCount < 1)
79 return v8::Undefined();
80
81 DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
82 ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document());
83
84 if (!scriptContext) {
85 V8Proxy::setDOMException(INVALID_ACCESS_ERR);
86 return v8::Undefined();
87 }
88
89 v8::Handle<v8::Value> function = args[0];
90 WTF::String functionString;
91 if (!function->IsFunction()) {
92 if (function->IsString())
93 functionString = toWebCoreString(function);
94 else {
95 v8::Handle<v8::Value> v8String = function->ToString();
96
97 // Bail out if string conversion failed.
98 if (v8String.IsEmpty())
99 return v8::Undefined();
100
101 functionString = toWebCoreString(v8String);
102 }
103
104 // Don't allow setting timeouts to run empty functions!
105 // (Bug 1009597)
106 if (functionString.length() == 0)
107 return v8::Undefined();
108 }
109
110 int32_t timeout = 0;
111 if (argumentCount >= 2)
112 timeout = args[1]->Int32Value();
113
114 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
115 return v8::Undefined();
116
117 int id;
118 if (function->IsFunction()) {
119 int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
120 v8::Local<v8::Value>* params = 0;
121 if (paramCount > 0) {
122 params = new v8::Local<v8::Value>[paramCount];
123 for (int i = 0; i < paramCount; i++)
124 // parameters must be globalized
125 params[i] = args[i+2];
126 }
127
128 // params is passed to action, and released in action's destructor
129 ScheduledAction* action = new ScheduledAction(V8Proxy::context(imp->frame()), v8::Handle<v8::Function>::Cast(function), paramCount, params);
130
131 delete[] params;
132
133 id = DOMTimer::install(scriptContext, action, timeout, singleShot);
134 } else {
135 if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval())
136 return v8::Integer::New(0);
137 id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot);
138 }
139
140 // Try to do the idle notification before the timeout expires to get better
141 // use of any idle time. Aim for the middle of the interval for simplicity.
142 if (timeout > 0) {
143 double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2;
144 V8GCForContextDispose::instance().notifyIdleSooner(maximumFireInterval);
145 }
146
147 return v8::Integer::New(id);
148 }
149
eventAccessorGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)150 v8::Handle<v8::Value> V8DOMWindow::eventAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
151 {
152 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), info.This());
153 if (holder.IsEmpty())
154 return v8::Undefined();
155
156 Frame* frame = V8DOMWindow::toNative(holder)->frame();
157 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true))
158 return v8::Undefined();
159
160 v8::Local<v8::Context> context = V8Proxy::context(frame);
161 if (context.IsEmpty())
162 return v8::Undefined();
163
164 v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event();
165 v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol);
166 if (jsEvent.IsEmpty())
167 return v8::Undefined();
168 return jsEvent;
169 }
170
eventAccessorSetter(v8::Local<v8::String> name,v8::Local<v8::Value> value,const v8::AccessorInfo & info)171 void V8DOMWindow::eventAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
172 {
173 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), info.This());
174 if (holder.IsEmpty())
175 return;
176
177 Frame* frame = V8DOMWindow::toNative(holder)->frame();
178 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true))
179 return;
180
181 v8::Local<v8::Context> context = V8Proxy::context(frame);
182 if (context.IsEmpty())
183 return;
184
185 v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event();
186 context->Global()->SetHiddenValue(eventSymbol, value);
187 }
188
locationAccessorSetter(v8::Local<v8::String> name,v8::Local<v8::Value> value,const v8::AccessorInfo & info)189 void V8DOMWindow::locationAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
190 {
191 DOMWindow* imp = V8DOMWindow::toNative(info.Holder());
192 State<V8Binding>* state = V8BindingState::Only();
193
194 DOMWindow* activeWindow = state->activeWindow();
195 if (!activeWindow)
196 return;
197
198 DOMWindow* firstWindow = state->firstWindow();
199 if (!firstWindow)
200 return;
201
202 imp->setLocation(toWebCoreString(value), activeWindow, firstWindow);
203 }
204
openerAccessorSetter(v8::Local<v8::String> name,v8::Local<v8::Value> value,const v8::AccessorInfo & info)205 void V8DOMWindow::openerAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
206 {
207 DOMWindow* imp = V8DOMWindow::toNative(info.Holder());
208
209 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
210 return;
211
212 // Opener can be shadowed if it is in the same domain.
213 // Have a special handling of null value to behave
214 // like Firefox. See bug http://b/1224887 & http://b/791706.
215 if (value->IsNull()) {
216 // imp->frame() cannot be null,
217 // otherwise, SameOrigin check would have failed.
218 ASSERT(imp->frame());
219 imp->frame()->loader()->setOpener(0);
220 }
221
222 // Delete the accessor from this object.
223 info.Holder()->Delete(name);
224
225 // Put property on the front (this) object.
226 info.This()->Set(name, value);
227 }
228
229 #if ENABLE(VIDEO)
230
AudioAccessorGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)231 v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
232 {
233 DOMWindow* window = V8DOMWindow::toNative(info.Holder());
234 return V8DOMWrapper::getConstructor(&V8HTMLAudioElementConstructor::info, window);
235 }
236
237 #endif
238
ImageAccessorGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)239 v8::Handle<v8::Value> V8DOMWindow::ImageAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
240 {
241 DOMWindow* window = V8DOMWindow::toNative(info.Holder());
242 return V8DOMWrapper::getConstructor(&V8HTMLImageElementConstructor::info, window);
243 }
244
OptionAccessorGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)245 v8::Handle<v8::Value> V8DOMWindow::OptionAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
246 {
247 DOMWindow* window = V8DOMWindow::toNative(info.Holder());
248 return V8DOMWrapper::getConstructor(&V8HTMLOptionElementConstructor::info, window);
249 }
250
addEventListenerCallback(const v8::Arguments & args)251 v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& args)
252 {
253 INC_STATS("DOM.DOMWindow.addEventListener()");
254
255 String eventType = toWebCoreString(args[0]);
256 bool useCapture = args[2]->BooleanValue();
257
258 DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
259
260 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
261 return v8::Undefined();
262
263 Document* doc = imp->document();
264
265 if (!doc)
266 return v8::Undefined();
267
268 // FIXME: Check if there is not enough arguments
269 V8Proxy* proxy = V8Proxy::retrieve(imp->frame());
270 if (!proxy)
271 return v8::Undefined();
272
273 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOrCreate);
274
275 if (listener) {
276 imp->addEventListener(eventType, listener, useCapture);
277 createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex);
278 }
279
280 return v8::Undefined();
281 }
282
283
removeEventListenerCallback(const v8::Arguments & args)284 v8::Handle<v8::Value> V8DOMWindow::removeEventListenerCallback(const v8::Arguments& args)
285 {
286 INC_STATS("DOM.DOMWindow.removeEventListener()");
287
288 String eventType = toWebCoreString(args[0]);
289 bool useCapture = args[2]->BooleanValue();
290
291 DOMWindow* imp = V8DOMWindow::toNative(args.Holder());
292
293 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true))
294 return v8::Undefined();
295
296 Document* doc = imp->document();
297
298 if (!doc)
299 return v8::Undefined();
300
301 V8Proxy* proxy = V8Proxy::retrieve(imp->frame());
302 if (!proxy)
303 return v8::Undefined();
304
305 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOnly);
306
307 if (listener) {
308 imp->removeEventListener(eventType, listener.get(), useCapture);
309 removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex);
310 }
311
312 return v8::Undefined();
313 }
314
postMessageCallback(const v8::Arguments & args)315 v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args)
316 {
317 INC_STATS("DOM.DOMWindow.postMessage()");
318 DOMWindow* window = V8DOMWindow::toNative(args.Holder());
319
320 DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow();
321 ASSERT(source->frame());
322
323 bool didThrow = false;
324 RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow);
325 if (didThrow)
326 return v8::Undefined();
327
328 MessagePortArray portArray;
329 String targetOrigin;
330
331 // This function has variable arguments and can either be:
332 // postMessage(message, port, targetOrigin);
333 // or
334 // postMessage(message, targetOrigin);
335 v8::TryCatch tryCatch;
336 if (args.Length() > 2) {
337 if (!getMessagePortArray(args[1], portArray))
338 return v8::Undefined();
339 targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
340 } else {
341 targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]);
342 }
343
344 if (tryCatch.HasCaught())
345 return v8::Undefined();
346
347 ExceptionCode ec = 0;
348 window->postMessage(message.release(), &portArray, targetOrigin, source, ec);
349 return throwError(ec);
350 }
351
352 // FIXME(fqian): returning string is cheating, and we should
353 // fix this by calling toString function on the receiver.
354 // However, V8 implements toString in JavaScript, which requires
355 // switching context of receiver. I consider it is dangerous.
toStringCallback(const v8::Arguments & args)356 v8::Handle<v8::Value> V8DOMWindow::toStringCallback(const v8::Arguments& args)
357 {
358 INC_STATS("DOM.DOMWindow.toString()");
359 v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), args.This());
360 if (domWrapper.IsEmpty())
361 return args.This()->ObjectProtoToString();
362 return domWrapper->ObjectProtoToString();
363 }
364
releaseEventsCallback(const v8::Arguments & args)365 v8::Handle<v8::Value> V8DOMWindow::releaseEventsCallback(const v8::Arguments& args)
366 {
367 INC_STATS("DOM.DOMWindow.nop()");
368 return v8::Undefined();
369 }
370
captureEventsCallback(const v8::Arguments & args)371 v8::Handle<v8::Value> V8DOMWindow::captureEventsCallback(const v8::Arguments& args)
372 {
373 INC_STATS("DOM.DOMWindow.nop()");
374 return v8::Undefined();
375 }
376
377 class DialogHandler {
378 public:
DialogHandler(v8::Handle<v8::Value> dialogArguments)379 explicit DialogHandler(v8::Handle<v8::Value> dialogArguments)
380 : m_dialogArguments(dialogArguments)
381 {
382 }
383
384 void dialogCreated(DOMWindow*);
385 v8::Handle<v8::Value> returnValue() const;
386
387 private:
388 v8::Handle<v8::Value> m_dialogArguments;
389 v8::Handle<v8::Context> m_dialogContext;
390 };
391
dialogCreated(DOMWindow * dialogFrame)392 inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame)
393 {
394 m_dialogContext = V8Proxy::context(dialogFrame->frame());
395 if (m_dialogContext.IsEmpty())
396 return;
397 if (m_dialogArguments.IsEmpty())
398 return;
399 v8::Context::Scope scope(m_dialogContext);
400 m_dialogContext->Global()->Set(v8::String::New("dialogArguments"), m_dialogArguments);
401 }
402
returnValue() const403 inline v8::Handle<v8::Value> DialogHandler::returnValue() const
404 {
405 if (m_dialogContext.IsEmpty())
406 return v8::Undefined();
407 v8::Context::Scope scope(m_dialogContext);
408 v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8::String::New("returnValue"));
409 if (returnValue.IsEmpty())
410 return v8::Undefined();
411 return returnValue;
412 }
413
setUpDialog(DOMWindow * dialog,void * handler)414 static void setUpDialog(DOMWindow* dialog, void* handler)
415 {
416 static_cast<DialogHandler*>(handler)->dialogCreated(dialog);
417 }
418
showModalDialogCallback(const v8::Arguments & args)419 v8::Handle<v8::Value> V8DOMWindow::showModalDialogCallback(const v8::Arguments& args)
420 {
421 INC_STATS("DOM.DOMWindow.showModalDialog()");
422 DOMWindow* impl = V8DOMWindow::toNative(args.Holder());
423
424 V8BindingState* state = V8BindingState::Only();
425
426 DOMWindow* activeWindow = state->activeWindow();
427 DOMWindow* firstWindow = state->firstWindow();
428
429 // FIXME: Handle exceptions properly.
430 String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
431 String dialogFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
432
433 DialogHandler handler(args[1]);
434
435 impl->showModalDialog(urlString, dialogFeaturesString, activeWindow, firstWindow, setUpDialog, &handler);
436
437 return handler.returnValue();
438 }
439
openCallback(const v8::Arguments & args)440 v8::Handle<v8::Value> V8DOMWindow::openCallback(const v8::Arguments& args)
441 {
442 INC_STATS("DOM.DOMWindow.open()");
443 DOMWindow* impl = V8DOMWindow::toNative(args.Holder());
444
445 V8BindingState* state = V8BindingState::Only();
446
447 DOMWindow* activeWindow = state->activeWindow();
448 DOMWindow* firstWindow = state->firstWindow();
449
450 // FIXME: Handle exceptions properly.
451 String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]);
452 AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1]));
453 String windowFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]);
454
455 RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeWindow, firstWindow);
456 if (!openedWindow)
457 return v8::Undefined();
458 return toV8(openedWindow.release());
459 }
460
indexedPropertyGetter(uint32_t index,const v8::AccessorInfo & info)461 v8::Handle<v8::Value> V8DOMWindow::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info)
462 {
463 INC_STATS("DOM.DOMWindow.IndexedPropertyGetter");
464
465 DOMWindow* window = V8DOMWindow::toNative(info.Holder());
466 if (!window)
467 return notHandledByInterceptor();
468
469 Frame* frame = window->frame();
470 if (!frame)
471 return notHandledByInterceptor();
472
473 Frame* child = frame->tree()->child(index);
474 if (child)
475 return toV8(child->domWindow());
476
477 return notHandledByInterceptor();
478 }
479
480
namedPropertyGetter(v8::Local<v8::String> name,const v8::AccessorInfo & info)481 v8::Handle<v8::Value> V8DOMWindow::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
482 {
483 INC_STATS("DOM.DOMWindow.NamedPropertyGetter");
484
485 DOMWindow* window = V8DOMWindow::toNative(info.Holder());
486 if (!window)
487 return notHandledByInterceptor();
488
489 Frame* frame = window->frame();
490 // window is detached from a frame.
491 if (!frame)
492 return notHandledByInterceptor();
493
494 // Search sub-frames.
495 AtomicString propName = v8StringToAtomicWebCoreString(name);
496 Frame* child = frame->tree()->child(propName);
497 if (child)
498 return toV8(child->domWindow());
499
500 // Search IDL functions defined in the prototype
501 v8::Handle<v8::Value> result = info.Holder()->GetRealNamedProperty(name);
502 if (!result.IsEmpty())
503 return result;
504
505 // Search named items in the document.
506 Document* doc = frame->document();
507
508 if (doc && doc->isHTMLDocument()) {
509 if (static_cast<HTMLDocument*>(doc)->hasNamedItem(propName.impl()) || doc->hasElementWithId(propName.impl())) {
510 RefPtr<HTMLCollection> items = doc->windowNamedItems(propName);
511 if (items->length() >= 1) {
512 if (items->length() == 1)
513 return toV8(items->firstItem());
514 return toV8(items.release());
515 }
516 }
517 }
518
519 return notHandledByInterceptor();
520 }
521
522
setTimeoutCallback(const v8::Arguments & args)523 v8::Handle<v8::Value> V8DOMWindow::setTimeoutCallback(const v8::Arguments& args)
524 {
525 INC_STATS("DOM.DOMWindow.setTimeout()");
526 return WindowSetTimeoutImpl(args, true);
527 }
528
529
setIntervalCallback(const v8::Arguments & args)530 v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args)
531 {
532 INC_STATS("DOM.DOMWindow.setInterval()");
533 return WindowSetTimeoutImpl(args, false);
534 }
535
namedSecurityCheck(v8::Local<v8::Object> host,v8::Local<v8::Value> key,v8::AccessType type,v8::Local<v8::Value>)536 bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
537 {
538 v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
539 if (window.IsEmpty())
540 return false; // the frame is gone.
541
542 DOMWindow* targetWindow = V8DOMWindow::toNative(window);
543
544 ASSERT(targetWindow);
545
546 Frame* target = targetWindow->frame();
547 if (!target)
548 return false;
549
550 if (key->IsString()) {
551 String name = toWebCoreString(key);
552 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
553 // because that would generate infinite recursion.
554 if (type == v8::ACCESS_HAS && target->tree()->child(name))
555 return true;
556 if (type == v8::ACCESS_GET && target->tree()->child(name) && !host->HasRealNamedProperty(key->ToString()))
557 return true;
558 }
559
560 return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false);
561 }
562
indexedSecurityCheck(v8::Local<v8::Object> host,uint32_t index,v8::AccessType type,v8::Local<v8::Value>)563 bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
564 {
565 v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host);
566 if (window.IsEmpty())
567 return false;
568
569 DOMWindow* targetWindow = V8DOMWindow::toNative(window);
570
571 ASSERT(targetWindow);
572
573 Frame* target = targetWindow->frame();
574 if (!target)
575 return false;
576
577 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
578 // because that would generate infinite recursion.
579 if (type == v8::ACCESS_HAS && target->tree()->child(index))
580 return true;
581 if (type == v8::ACCESS_GET && target->tree()->child(index) && !host->HasRealIndexedProperty(index))
582 return true;
583
584 return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false);
585 }
586
toV8(DOMWindow * window)587 v8::Handle<v8::Value> toV8(DOMWindow* window)
588 {
589 if (!window)
590 return v8::Null();
591 // Initializes environment of a frame, and return the global object
592 // of the frame.
593 Frame* frame = window->frame();
594 if (!frame)
595 return v8::Handle<v8::Object>();
596
597 // Special case: Because of evaluateInIsolatedWorld() one DOMWindow can have
598 // multiple contexts and multiple global objects associated with it. When
599 // code running in one of those contexts accesses the window object, we
600 // want to return the global object associated with that context, not
601 // necessarily the first global object associated with that DOMWindow.
602 v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent();
603 v8::Handle<v8::Object> currentGlobal = currentContext->Global();
604 v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), currentGlobal);
605 if (!windowWrapper.IsEmpty()) {
606 if (V8DOMWindow::toNative(windowWrapper) == window)
607 return currentGlobal;
608 }
609
610 // Otherwise, return the global object associated with this frame.
611 v8::Handle<v8::Context> context = V8Proxy::context(frame);
612 if (context.IsEmpty())
613 return v8::Handle<v8::Object>();
614
615 v8::Handle<v8::Object> global = context->Global();
616 ASSERT(!global.IsEmpty());
617 return global;
618 }
619
620 } // namespace WebCore
621