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