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