• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009, 2011 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 "V8Window.h"
33 
34 #include "V8HTMLCollection.h"
35 #include "V8Node.h"
36 #include "bindings/v8/BindingSecurity.h"
37 #include "bindings/v8/ExceptionMessages.h"
38 #include "bindings/v8/ExceptionState.h"
39 #include "bindings/v8/ScheduledAction.h"
40 #include "bindings/v8/ScriptController.h"
41 #include "bindings/v8/ScriptSourceCode.h"
42 #include "bindings/v8/SerializedScriptValue.h"
43 #include "bindings/v8/V8Binding.h"
44 #include "bindings/v8/V8EventListener.h"
45 #include "bindings/v8/V8EventListenerList.h"
46 #include "bindings/v8/V8GCForContextDispose.h"
47 #include "bindings/v8/V8HiddenPropertyName.h"
48 #include "bindings/v8/V8Utilities.h"
49 #include "core/dom/ExceptionCode.h"
50 #include "core/dom/MessagePort.h"
51 #include "core/html/HTMLCollection.h"
52 #include "core/html/HTMLDocument.h"
53 #include "core/inspector/ScriptCallStack.h"
54 #include "core/loader/FrameLoadRequest.h"
55 #include "core/loader/FrameLoader.h"
56 #include "core/frame/ContentSecurityPolicy.h"
57 #include "core/frame/DOMTimer.h"
58 #include "core/frame/DOMWindow.h"
59 #include "core/frame/DOMWindowTimers.h"
60 #include "core/frame/Frame.h"
61 #include "core/frame/FrameView.h"
62 #include "core/frame/Settings.h"
63 #include "core/storage/Storage.h"
64 #include "platform/PlatformScreen.h"
65 #include "platform/graphics/media/MediaPlayer.h"
66 #include "wtf/ArrayBuffer.h"
67 #include "wtf/Assertions.h"
68 #include "wtf/OwnPtr.h"
69 
70 namespace WebCore {
71 
72 // FIXME: There is a lot of duplication with SetTimeoutOrInterval() in V8WorkerGlobalScopeCustom.cpp.
73 // We should refactor this.
WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value> & info,bool singleShot,ExceptionState & exceptionState)74 void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot, ExceptionState& exceptionState)
75 {
76     int argumentCount = info.Length();
77 
78     if (argumentCount < 1)
79         return;
80 
81     DOMWindow* imp = V8Window::toNative(info.Holder());
82     if (!imp->document()) {
83         exceptionState.throwDOMException(InvalidAccessError, "No script context is available in which to execute the script.");
84         return;
85     }
86 
87     v8::Handle<v8::Value> function = info[0];
88     String functionString;
89     if (!function->IsFunction()) {
90         if (function->IsString()) {
91             functionString = toCoreString(function.As<v8::String>());
92         } else {
93             v8::Handle<v8::String> v8String = function->ToString();
94 
95             // Bail out if string conversion failed.
96             if (v8String.IsEmpty())
97                 return;
98 
99             functionString = toCoreString(v8String);
100         }
101 
102         // Don't allow setting timeouts to run empty functions!
103         // (Bug 1009597)
104         if (!functionString.length())
105             return;
106     }
107 
108     if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState))
109         return;
110 
111     OwnPtr<ScheduledAction> action;
112     if (function->IsFunction()) {
113         int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0;
114         OwnPtr<v8::Local<v8::Value>[]> params;
115         if (paramCount > 0) {
116             params = adoptArrayPtr(new v8::Local<v8::Value>[paramCount]);
117             for (int i = 0; i < paramCount; i++) {
118                 // parameters must be globalized
119                 params[i] = info[i+2];
120             }
121         }
122 
123         // params is passed to action, and released in action's destructor
124         ASSERT(imp->frame());
125         action = adoptPtr(new ScheduledAction(imp->frame()->script().currentWorldContext(), v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate()));
126     } else {
127         if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval()) {
128             v8SetReturnValue(info, 0);
129             return;
130         }
131         ASSERT(imp->frame());
132         action = adoptPtr(new ScheduledAction(imp->frame()->script().currentWorldContext(), functionString, KURL(), info.GetIsolate()));
133     }
134 
135     int32_t timeout = argumentCount >= 2 ? info[1]->Int32Value() : 0;
136     int timerId;
137     if (singleShot)
138         timerId = DOMWindowTimers::setTimeout(imp, action.release(), timeout);
139     else
140         timerId = DOMWindowTimers::setInterval(imp, action.release(), timeout);
141 
142     // Try to do the idle notification before the timeout expires to get better
143     // use of any idle time. Aim for the middle of the interval for simplicity.
144     if (timeout >= 0) {
145         double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2;
146         V8GCForContextDispose::instanceTemplate().notifyIdleSooner(maximumFireInterval);
147     }
148 
149     v8SetReturnValue(info, timerId);
150 }
151 
eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value> & info)152 void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
153 {
154     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate())));
155     if (holder.IsEmpty())
156         return;
157 
158     Frame* frame = V8Window::toNative(holder)->frame();
159     ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Window", info.Holder(), info.GetIsolate());
160     if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) {
161         exceptionState.throwIfNeeded();
162         return;
163     }
164 
165     ASSERT(frame);
166     v8::Local<v8::Context> context = frame->script().currentWorldContext();
167     if (context.IsEmpty())
168         return;
169 
170     v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate());
171     v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol);
172     if (jsEvent.IsEmpty())
173         return;
174     v8SetReturnValue(info, jsEvent);
175 }
176 
eventAttributeSetterCustom(v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)177 void V8Window::eventAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
178 {
179     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate())));
180     if (holder.IsEmpty())
181         return;
182 
183     Frame* frame = V8Window::toNative(holder)->frame();
184     ExceptionState exceptionState(ExceptionState::SetterContext, "event", "Window", info.Holder(), info.GetIsolate());
185     if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) {
186         exceptionState.throwIfNeeded();
187         return;
188     }
189 
190     ASSERT(frame);
191     v8::Local<v8::Context> context = frame->script().currentWorldContext();
192     if (context.IsEmpty())
193         return;
194 
195     v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate());
196     context->Global()->SetHiddenValue(eventSymbol, value);
197 }
198 
frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value> & info)199 void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info)
200 {
201     DOMWindow* imp = V8Window::toNative(info.Holder());
202     ExceptionState exceptionState(ExceptionState::GetterContext, "frame", "Window", info.Holder(), info.GetIsolate());
203     if (!BindingSecurity::shouldAllowAccessToNode(imp->frameElement(), exceptionState)) {
204         v8SetReturnValueNull(info);
205         exceptionState.throwIfNeeded();
206         return;
207     }
208 
209     // The wrapper for an <iframe> should get its prototype from the context of the frame it's in, rather than its own frame.
210     // So, use its containing document as the creation context when wrapping.
211     v8::Handle<v8::Value> creationContext = toV8(&imp->frameElement()->document(), v8::Handle<v8::Object>(), info.GetIsolate());
212     RELEASE_ASSERT(!creationContext.IsEmpty());
213     v8::Handle<v8::Value> wrapper = toV8(imp->frameElement(), v8::Handle<v8::Object>::Cast(creationContext), info.GetIsolate());
214     v8SetReturnValue(info, wrapper);
215 }
216 
openerAttributeSetterCustom(v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<void> & info)217 void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
218 {
219     DOMWindow* imp = V8Window::toNative(info.Holder());
220     ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), info.GetIsolate());
221     if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) {
222         exceptionState.throwIfNeeded();
223         return;
224     }
225 
226     // Opener can be shadowed if it is in the same domain.
227     // Have a special handling of null value to behave
228     // like Firefox. See bug http://b/1224887 & http://b/791706.
229     if (value->IsNull()) {
230         // imp->frame() cannot be null,
231         // otherwise, SameOrigin check would have failed.
232         ASSERT(imp->frame());
233         imp->frame()->loader().setOpener(0);
234     }
235 
236     // Delete the accessor from this object.
237     info.Holder()->Delete(v8AtomicString(info.GetIsolate(), "opener"));
238 
239     // Put property on the front (this) object.
240     info.This()->Set(v8AtomicString(info.GetIsolate(), "opener"), value);
241 }
242 
isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value)243 static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value)
244 {
245     if (value->IsString() || value->IsStringObject())
246         return true;
247     return false;
248 }
249 
250 
postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> & info)251 void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
252 {
253     // None of these need to be RefPtr because info and context are guaranteed
254     // to hold on to them.
255     DOMWindow* window = V8Window::toNative(info.Holder());
256     DOMWindow* source = activeDOMWindow();
257 
258     // If called directly by WebCore we don't have a calling context.
259     if (!source) {
260         throwUninformativeAndGenericTypeError(info.GetIsolate());
261         return;
262     }
263 
264     // This function has variable arguments and can be:
265     // Per current spec:
266     //   postMessage(message, targetOrigin)
267     //   postMessage(message, targetOrigin, {sequence of transferrables})
268     // Legacy non-standard implementations in webkit allowed:
269     //   postMessage(message, {sequence of transferrables}, targetOrigin);
270     MessagePortArray portArray;
271     ArrayBufferArray arrayBufferArray;
272     int targetOriginArgIndex = 1;
273     if (info.Length() > 2) {
274         int transferablesArgIndex = 2;
275         if (isLegacyTargetOriginDesignation(info[2])) {
276             targetOriginArgIndex = 2;
277             transferablesArgIndex = 1;
278         }
279         bool notASequence = false;
280         if (!extractTransferables(info[transferablesArgIndex], portArray, arrayBufferArray, notASequence, info.GetIsolate())) {
281             if (notASequence)
282                 throwTypeError(ExceptionMessages::failedToExecute("postMessage", "Window", ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)), info.GetIsolate());
283             return;
284         }
285     }
286     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info[targetOriginArgIndex]);
287 
288     bool didThrow = false;
289     RefPtr<SerializedScriptValue> message =
290         SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, didThrow, info.GetIsolate());
291     if (didThrow)
292         return;
293 
294     ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "Window", info.Holder(), info.GetIsolate());
295     window->postMessage(message.release(), &portArray, targetOrigin, source, exceptionState);
296     exceptionState.throwIfNeeded();
297 }
298 
299 // FIXME(fqian): returning string is cheating, and we should
300 // fix this by calling toString function on the receiver.
301 // However, V8 implements toString in JavaScript, which requires
302 // switching context of receiver. I consider it is dangerous.
toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value> & info)303 void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
304 {
305     v8::Handle<v8::Object> domWrapper = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate())));
306     if (domWrapper.IsEmpty()) {
307         v8SetReturnValue(info, info.This()->ObjectProtoToString());
308         return;
309     }
310     v8SetReturnValue(info, domWrapper->ObjectProtoToString());
311 }
312 
313 class DialogHandler {
314 public:
DialogHandler(v8::Handle<v8::Value> dialogArguments)315     explicit DialogHandler(v8::Handle<v8::Value> dialogArguments)
316         : m_dialogArguments(dialogArguments)
317     {
318     }
319 
320     void dialogCreated(DOMWindow*, v8::Isolate*);
321     v8::Handle<v8::Value> returnValue(v8::Isolate*) const;
322 
323 private:
324     v8::Handle<v8::Value> m_dialogArguments;
325     v8::Handle<v8::Context> m_dialogContext;
326 };
327 
dialogCreated(DOMWindow * dialogFrame,v8::Isolate * isolate)328 inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame, v8::Isolate* isolate)
329 {
330     m_dialogContext = dialogFrame->frame() ? dialogFrame->frame()->script().currentWorldContext() : v8::Local<v8::Context>();
331     if (m_dialogContext.IsEmpty())
332         return;
333     if (m_dialogArguments.IsEmpty())
334         return;
335     v8::Context::Scope scope(m_dialogContext);
336     m_dialogContext->Global()->Set(v8AtomicString(isolate, "dialogArguments"), m_dialogArguments);
337 }
338 
returnValue(v8::Isolate * isolate) const339 inline v8::Handle<v8::Value> DialogHandler::returnValue(v8::Isolate* isolate) const
340 {
341     if (m_dialogContext.IsEmpty())
342         return v8::Undefined(isolate);
343     v8::Context::Scope scope(m_dialogContext);
344     v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8AtomicString(isolate, "returnValue"));
345     if (returnValue.IsEmpty())
346         return v8::Undefined(isolate);
347     return returnValue;
348 }
349 
setUpDialog(DOMWindow * dialog,void * handler)350 static void setUpDialog(DOMWindow* dialog, void* handler)
351 {
352     static_cast<DialogHandler*>(handler)->dialogCreated(dialog, v8::Isolate::GetCurrent());
353 }
354 
showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Value> & info)355 void V8Window::showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
356 {
357     DOMWindow* impl = V8Window::toNative(info.Holder());
358     ExceptionState exceptionState(ExceptionState::ExecutionContext, "showModalDialog", "Window", info.Holder(), info.GetIsolate());
359     if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame(), exceptionState)) {
360         exceptionState.throwIfNeeded();
361         return;
362     }
363 
364     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]);
365     DialogHandler handler(info[1]);
366     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesString, info[2]);
367 
368     impl->showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(), firstDOMWindow(), setUpDialog, &handler);
369 
370     v8SetReturnValue(info, handler.returnValue(info.GetIsolate()));
371 }
372 
openMethodCustom(const v8::FunctionCallbackInfo<v8::Value> & info)373 void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
374 {
375     DOMWindow* impl = V8Window::toNative(info.Holder());
376     ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Window", info.Holder(), info.GetIsolate());
377     if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame(), exceptionState)) {
378         exceptionState.throwIfNeeded();
379         return;
380     }
381 
382     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]);
383     AtomicString frameName;
384     if (info[1]->IsUndefined() || info[1]->IsNull()) {
385         frameName = "_blank";
386     } else {
387         V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, frameNameResource, info[1]);
388         frameName = frameNameResource;
389     }
390     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesString, info[2]);
391 
392     RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeDOMWindow(), firstDOMWindow());
393     if (!openedWindow)
394         return;
395 
396     v8SetReturnValueFast(info, openedWindow.release(), impl);
397 }
398 
namedPropertyGetterCustom(v8::Local<v8::String> name,const v8::PropertyCallbackInfo<v8::Value> & info)399 void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
400 {
401 
402     DOMWindow* window = V8Window::toNative(info.Holder());
403     if (!window)
404         return;
405 
406     Frame* frame = window->frame();
407     // window is detached from a frame.
408     if (!frame)
409         return;
410 
411     // Search sub-frames.
412     AtomicString propName = toCoreAtomicString(name);
413     Frame* child = frame->tree().scopedChild(propName);
414     if (child) {
415         v8SetReturnValueFast(info, child->domWindow(), window);
416         return;
417     }
418 
419     // Search IDL functions defined in the prototype
420     if (!info.Holder()->GetRealNamedProperty(name).IsEmpty())
421         return;
422 
423     // Search named items in the document.
424     Document* doc = frame->document();
425 
426     if (doc && doc->isHTMLDocument()) {
427         if (toHTMLDocument(doc)->hasNamedItem(propName) || doc->hasElementWithId(propName.impl())) {
428             RefPtr<HTMLCollection> items = doc->windowNamedItems(propName);
429             if (!items->isEmpty()) {
430                 if (items->hasExactlyOneItem()) {
431                     v8SetReturnValueFast(info, items->item(0), window);
432                     return;
433                 }
434                 v8SetReturnValueFast(info, items.release(), window);
435                 return;
436             }
437         }
438     }
439 }
440 
441 
setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value> & info)442 void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
443 {
444     ExceptionState exceptionState(ExceptionState::ExecutionContext, "setTimeout", "Window", info.Holder(), info.GetIsolate());
445     WindowSetTimeoutImpl(info, true, exceptionState);
446     exceptionState.throwIfNeeded();
447 }
448 
449 
setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value> & info)450 void V8Window::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
451 {
452     ExceptionState exceptionState(ExceptionState::ExecutionContext, "setInterval", "Window", info.Holder(), info.GetIsolate());
453     WindowSetTimeoutImpl(info, false, exceptionState);
454     exceptionState.throwIfNeeded();
455 }
456 
namedSecurityCheckCustom(v8::Local<v8::Object> host,v8::Local<v8::Value> key,v8::AccessType type,v8::Local<v8::Value>)457 bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>)
458 {
459     v8::Isolate* isolate = v8::Isolate::GetCurrent();
460     v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate)));
461     if (window.IsEmpty())
462         return false; // the frame is gone.
463 
464     DOMWindow* targetWindow = V8Window::toNative(window);
465 
466     ASSERT(targetWindow);
467 
468     Frame* target = targetWindow->frame();
469     if (!target)
470         return false;
471 
472     // Notify the loader's client if the initial document has been accessed.
473     if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument())
474         target->loader().didAccessInitialDocument();
475 
476     if (key->IsString()) {
477         DEFINE_STATIC_LOCAL(const AtomicString, nameOfProtoProperty, ("__proto__", AtomicString::ConstructFromLiteral));
478 
479         AtomicString name = toCoreAtomicString(key.As<v8::String>());
480         Frame* childFrame = target->tree().scopedChild(name);
481         // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
482         // because that would generate infinite recursion.
483         if (type == v8::ACCESS_HAS && childFrame)
484             return true;
485         // We need to explicitly compare against nameOfProtoProperty because
486         // V8's JSObject::LocalLookup finds __proto__ before
487         // interceptors and even when __proto__ isn't a "real named property".
488         v8::Handle<v8::String> keyString = key.As<v8::String>();
489         if (type == v8::ACCESS_GET
490             && childFrame
491             && !host->HasRealNamedProperty(keyString)
492             && !window->HasRealNamedProperty(keyString)
493             && name != nameOfProtoProperty)
494             return true;
495     }
496 
497     return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError);
498 }
499 
indexedSecurityCheckCustom(v8::Local<v8::Object> host,uint32_t index,v8::AccessType type,v8::Local<v8::Value>)500 bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>)
501 {
502     v8::Isolate* isolate = v8::Isolate::GetCurrent();
503     v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate)));
504     if (window.IsEmpty())
505         return false;
506 
507     DOMWindow* targetWindow = V8Window::toNative(window);
508 
509     ASSERT(targetWindow);
510 
511     Frame* target = targetWindow->frame();
512     if (!target)
513         return false;
514 
515     // Notify the loader's client if the initial document has been accessed.
516     if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument())
517         target->loader().didAccessInitialDocument();
518 
519     Frame* childFrame =  target->tree().scopedChild(index);
520 
521     // Notice that we can't call HasRealNamedProperty for ACCESS_HAS
522     // because that would generate infinite recursion.
523     if (type == v8::ACCESS_HAS && childFrame)
524         return true;
525     if (type == v8::ACCESS_GET
526         && childFrame
527         && !host->HasRealIndexedProperty(index)
528         && !window->HasRealIndexedProperty(index))
529         return true;
530 
531     return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError);
532 }
533 
toV8(DOMWindow * window,v8::Handle<v8::Object> creationContext,v8::Isolate * isolate)534 v8::Handle<v8::Value> toV8(DOMWindow* window, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate)
535 {
536     // Notice that we explicitly ignore creationContext because the DOMWindow is its own creationContext.
537 
538     if (!window)
539         return v8::Null(isolate);
540     // Initializes environment of a frame, and return the global object
541     // of the frame.
542     Frame* frame = window->frame();
543     if (!frame)
544         return v8Undefined();
545 
546     // Special case: Because of executeScriptInIsolatedWorld() one DOMWindow can have
547     // multiple contexts and multiple global objects associated with it. When
548     // code running in one of those contexts accesses the window object, we
549     // want to return the global object associated with that context, not
550     // necessarily the first global object associated with that DOMWindow.
551     v8::Handle<v8::Context> currentContext = isolate->GetCurrentContext();
552     v8::Handle<v8::Object> currentGlobal = currentContext->Global();
553     v8::Handle<v8::Object> windowWrapper = currentGlobal->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate)));
554     if (!windowWrapper.IsEmpty()) {
555         if (V8Window::toNative(windowWrapper) == window)
556             return currentGlobal;
557     }
558 
559     // Otherwise, return the global object associated with this frame.
560     v8::Handle<v8::Context> context = frame->script().currentWorldContext();
561     if (context.IsEmpty())
562         return v8Undefined();
563 
564     v8::Handle<v8::Object> global = context->Global();
565     ASSERT(!global.IsEmpty());
566     return global;
567 }
568 
569 } // namespace WebCore
570