• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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