OLD | NEW |
| (Empty) |
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/ScheduledAction.h" | |
38 #include "bindings/v8/ScriptController.h" | |
39 #include "bindings/v8/ScriptSourceCode.h" | |
40 #include "bindings/v8/SerializedScriptValue.h" | |
41 #include "bindings/v8/V8Binding.h" | |
42 #include "bindings/v8/V8EventListener.h" | |
43 #include "bindings/v8/V8EventListenerList.h" | |
44 #include "bindings/v8/V8GCForContextDispose.h" | |
45 #include "bindings/v8/V8HiddenPropertyName.h" | |
46 #include "bindings/v8/V8Utilities.h" | |
47 #include "core/dom/ExceptionCode.h" | |
48 #include "core/dom/MessagePort.h" | |
49 #include "core/html/HTMLCollection.h" | |
50 #include "core/html/HTMLDocument.h" | |
51 #include "core/inspector/ScriptCallStack.h" | |
52 #include "core/loader/FrameLoadRequest.h" | |
53 #include "core/loader/FrameLoader.h" | |
54 #include "core/page/Chrome.h" | |
55 #include "core/page/ContentSecurityPolicy.h" | |
56 #include "core/page/DOMTimer.h" | |
57 #include "core/page/DOMWindow.h" | |
58 #include "core/page/Frame.h" | |
59 #include "core/page/FrameView.h" | |
60 #include "core/page/Location.h" | |
61 #include "core/page/Page.h" | |
62 #include "core/page/Settings.h" | |
63 #include "core/page/WindowFeatures.h" | |
64 #include "core/platform/PlatformScreen.h" | |
65 #include "core/platform/graphics/MediaPlayer.h" | |
66 #include "core/storage/Storage.h" | |
67 #include "core/workers/SharedWorkerRepository.h" | |
68 #include "wtf/ArrayBuffer.h" | |
69 | |
70 namespace WebCore { | |
71 | |
72 void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& args, bool
singleShot) | |
73 { | |
74 int argumentCount = args.Length(); | |
75 | |
76 if (argumentCount < 1) | |
77 return; | |
78 | |
79 DOMWindow* imp = V8Window::toNative(args.Holder()); | |
80 ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>
(imp->document()); | |
81 | |
82 if (!scriptContext) { | |
83 setDOMException(INVALID_ACCESS_ERR, args.GetIsolate()); | |
84 return; | |
85 } | |
86 | |
87 v8::Handle<v8::Value> function = args[0]; | |
88 WTF::String functionString; | |
89 if (!function->IsFunction()) { | |
90 if (function->IsString()) { | |
91 functionString = toWebCoreString(function); | |
92 } else { | |
93 v8::Handle<v8::Value> v8String = function->ToString(); | |
94 | |
95 // Bail out if string conversion failed. | |
96 if (v8String.IsEmpty()) | |
97 return; | |
98 | |
99 functionString = toWebCoreString(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 int32_t timeout = 0; | |
109 if (argumentCount >= 2) | |
110 timeout = args[1]->Int32Value(); | |
111 | |
112 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
113 return; | |
114 | |
115 int id; | |
116 if (function->IsFunction()) { | |
117 int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; | |
118 v8::Local<v8::Value>* params = 0; | |
119 if (paramCount > 0) { | |
120 params = new v8::Local<v8::Value>[paramCount]; | |
121 for (int i = 0; i < paramCount; i++) { | |
122 // parameters must be globalized | |
123 params[i] = args[i+2]; | |
124 } | |
125 } | |
126 | |
127 // params is passed to action, and released in action's destructor | |
128 ASSERT(imp->frame()); | |
129 OwnPtr<ScheduledAction> action = adoptPtr(new ScheduledAction(imp->frame
()->script()->currentWorldContext(), v8::Handle<v8::Function>::Cast(function), p
aramCount, params, args.GetIsolate())); | |
130 | |
131 // FIXME: We should use OwnArrayPtr for params. | |
132 delete[] params; | |
133 | |
134 id = DOMTimer::install(scriptContext, action.release(), timeout, singleS
hot); | |
135 } else { | |
136 if (imp->document() && !imp->document()->contentSecurityPolicy()->allowE
val()) { | |
137 v8SetReturnValue(args, 0); | |
138 return; | |
139 } | |
140 ASSERT(imp->frame()); | |
141 id = DOMTimer::install(scriptContext, adoptPtr(new ScheduledAction(imp->
frame()->script()->currentWorldContext(), functionString, KURL(), args.GetIsolat
e())), timeout, singleShot); | |
142 } | |
143 | |
144 // Try to do the idle notification before the timeout expires to get better | |
145 // use of any idle time. Aim for the middle of the interval for simplicity. | |
146 if (timeout >= 0) { | |
147 double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2; | |
148 V8GCForContextDispose::instance().notifyIdleSooner(maximumFireInterval); | |
149 } | |
150 | |
151 v8SetReturnValue(args, id); | |
152 } | |
153 | |
154 void V8Window::eventAttrGetterCustom(v8::Local<v8::String> name, const v8::Prope
rtyCallbackInfo<v8::Value>& info) | |
155 { | |
156 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8
Window::GetTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))
); | |
157 if (holder.IsEmpty()) | |
158 return; | |
159 | |
160 Frame* frame = V8Window::toNative(holder)->frame(); | |
161 if (!BindingSecurity::shouldAllowAccessToFrame(frame)) | |
162 return; | |
163 | |
164 ASSERT(frame); | |
165 v8::Local<v8::Context> context = frame->script()->currentWorldContext(); | |
166 if (context.IsEmpty()) | |
167 return; | |
168 | |
169 v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(); | |
170 v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbo
l); | |
171 if (jsEvent.IsEmpty()) | |
172 return; | |
173 v8SetReturnValue(info, jsEvent); | |
174 } | |
175 | |
176 void V8Window::eventAttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::V
alue> value, const v8::PropertyCallbackInfo<void>& info) | |
177 { | |
178 v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8
Window::GetTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))
); | |
179 if (holder.IsEmpty()) | |
180 return; | |
181 | |
182 Frame* frame = V8Window::toNative(holder)->frame(); | |
183 if (!BindingSecurity::shouldAllowAccessToFrame(frame)) | |
184 return; | |
185 | |
186 ASSERT(frame); | |
187 v8::Local<v8::Context> context = frame->script()->currentWorldContext(); | |
188 if (context.IsEmpty()) | |
189 return; | |
190 | |
191 v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(); | |
192 context->Global()->SetHiddenValue(eventSymbol, value); | |
193 } | |
194 | |
195 void V8Window::locationAttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8
::Value> value, const v8::PropertyCallbackInfo<void>& info) | |
196 { | |
197 DOMWindow* imp = V8Window::toNative(info.Holder()); | |
198 | |
199 DOMWindow* active = activeDOMWindow(); | |
200 if (!active) | |
201 return; | |
202 | |
203 DOMWindow* first = firstDOMWindow(); | |
204 if (!first) | |
205 return; | |
206 | |
207 if (Location* location = imp->location()) | |
208 location->setHref(active, first, toWebCoreString(value)); | |
209 } | |
210 | |
211 void V8Window::openerAttrSetterCustom(v8::Local<v8::String> name, v8::Local<v8::
Value> value, const v8::PropertyCallbackInfo<void>& info) | |
212 { | |
213 DOMWindow* imp = V8Window::toNative(info.Holder()); | |
214 | |
215 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
216 return; | |
217 | |
218 // Opener can be shadowed if it is in the same domain. | |
219 // Have a special handling of null value to behave | |
220 // like Firefox. See bug http://b/1224887 & http://b/791706. | |
221 if (value->IsNull()) { | |
222 // imp->frame() cannot be null, | |
223 // otherwise, SameOrigin check would have failed. | |
224 ASSERT(imp->frame()); | |
225 imp->frame()->loader()->setOpener(0); | |
226 } | |
227 | |
228 // Delete the accessor from this object. | |
229 info.Holder()->Delete(name); | |
230 | |
231 // Put property on the front (this) object. | |
232 info.This()->Set(name, value); | |
233 } | |
234 | |
235 void V8Window::addEventListenerMethodCustom(const v8::FunctionCallbackInfo<v8::V
alue>& args) | |
236 { | |
237 String eventType = toWebCoreString(args[0]); | |
238 bool useCapture = args[2]->BooleanValue(); | |
239 | |
240 DOMWindow* imp = V8Window::toNative(args.Holder()); | |
241 | |
242 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
243 return; | |
244 | |
245 Document* doc = imp->document(); | |
246 | |
247 if (!doc) | |
248 return; | |
249 | |
250 // FIXME: Check if there is not enough arguments | |
251 if (!imp->frame()) | |
252 return; | |
253 | |
254 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[
1], false, ListenerFindOrCreate); | |
255 | |
256 if (listener) { | |
257 imp->addEventListener(eventType, listener, useCapture); | |
258 createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex,
args.GetIsolate()); | |
259 } | |
260 } | |
261 | |
262 | |
263 void V8Window::removeEventListenerMethodCustom(const v8::FunctionCallbackInfo<v8
::Value>& args) | |
264 { | |
265 String eventType = toWebCoreString(args[0]); | |
266 bool useCapture = args[2]->BooleanValue(); | |
267 | |
268 DOMWindow* imp = V8Window::toNative(args.Holder()); | |
269 | |
270 if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame())) | |
271 return; | |
272 | |
273 Document* doc = imp->document(); | |
274 | |
275 if (!doc) | |
276 return; | |
277 | |
278 if (!imp->frame()) | |
279 return; | |
280 | |
281 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(args[
1], false, ListenerFindOnly); | |
282 | |
283 if (listener) { | |
284 imp->removeEventListener(eventType, listener.get(), useCapture); | |
285 removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex,
args.GetIsolate()); | |
286 } | |
287 } | |
288 | |
289 static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value) | |
290 { | |
291 if (value->IsString() || value->IsStringObject()) | |
292 return true; | |
293 return false; | |
294 } | |
295 | |
296 | |
297 void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>
& args) | |
298 { | |
299 // None of these need to be RefPtr because args and context are guaranteed | |
300 // to hold on to them. | |
301 DOMWindow* window = V8Window::toNative(args.Holder()); | |
302 DOMWindow* source = activeDOMWindow(); | |
303 | |
304 // If called directly by WebCore we don't have a calling context. | |
305 if (!source) { | |
306 throwTypeError(0, args.GetIsolate()); | |
307 return; | |
308 } | |
309 | |
310 // This function has variable arguments and can be: | |
311 // Per current spec: | |
312 // postMessage(message, targetOrigin) | |
313 // postMessage(message, targetOrigin, {sequence of transferrables}) | |
314 // Legacy non-standard implementations in webkit allowed: | |
315 // postMessage(message, {sequence of transferrables}, targetOrigin); | |
316 MessagePortArray portArray; | |
317 ArrayBufferArray arrayBufferArray; | |
318 int targetOriginArgIndex = 1; | |
319 if (args.Length() > 2) { | |
320 int transferablesArgIndex = 2; | |
321 if (isLegacyTargetOriginDesignation(args[2])) { | |
322 targetOriginArgIndex = 2; | |
323 transferablesArgIndex = 1; | |
324 } | |
325 if (!extractTransferables(args[transferablesArgIndex], portArray, arrayB
ufferArray, args.GetIsolate())) | |
326 return; | |
327 } | |
328 V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullChe
ck>, targetOrigin, args[targetOriginArgIndex]); | |
329 | |
330 bool didThrow = false; | |
331 RefPtr<SerializedScriptValue> message = | |
332 SerializedScriptValue::create(args[0], &portArray, &arrayBufferArray, di
dThrow, args.GetIsolate()); | |
333 if (didThrow) | |
334 return; | |
335 | |
336 ExceptionCode ec = 0; | |
337 window->postMessage(message.release(), &portArray, targetOrigin, source, ec)
; | |
338 setDOMException(ec, args.GetIsolate()); | |
339 } | |
340 | |
341 // FIXME(fqian): returning string is cheating, and we should | |
342 // fix this by calling toString function on the receiver. | |
343 // However, V8 implements toString in JavaScript, which requires | |
344 // switching context of receiver. I consider it is dangerous. | |
345 void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& a
rgs) | |
346 { | |
347 v8::Handle<v8::Object> domWrapper = args.This()->FindInstanceInPrototypeChai
n(V8Window::GetTemplate(args.GetIsolate(), worldTypeInMainThread(args.GetIsolate
()))); | |
348 if (domWrapper.IsEmpty()) { | |
349 v8SetReturnValue(args, args.This()->ObjectProtoToString()); | |
350 return; | |
351 } | |
352 v8SetReturnValue(args, domWrapper->ObjectProtoToString()); | |
353 } | |
354 | |
355 class DialogHandler { | |
356 public: | |
357 explicit DialogHandler(v8::Handle<v8::Value> dialogArguments) | |
358 : m_dialogArguments(dialogArguments) | |
359 { | |
360 } | |
361 | |
362 void dialogCreated(DOMWindow*); | |
363 v8::Handle<v8::Value> returnValue() const; | |
364 | |
365 private: | |
366 v8::Handle<v8::Value> m_dialogArguments; | |
367 v8::Handle<v8::Context> m_dialogContext; | |
368 }; | |
369 | |
370 inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame) | |
371 { | |
372 m_dialogContext = dialogFrame->frame() ? dialogFrame->frame()->script()->cur
rentWorldContext() : v8::Local<v8::Context>(); | |
373 if (m_dialogContext.IsEmpty()) | |
374 return; | |
375 if (m_dialogArguments.IsEmpty()) | |
376 return; | |
377 v8::Context::Scope scope(m_dialogContext); | |
378 m_dialogContext->Global()->Set(v8::String::NewSymbol("dialogArguments"), m_d
ialogArguments); | |
379 } | |
380 | |
381 inline v8::Handle<v8::Value> DialogHandler::returnValue() const | |
382 { | |
383 if (m_dialogContext.IsEmpty()) | |
384 return v8::Undefined(); | |
385 v8::Context::Scope scope(m_dialogContext); | |
386 v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8::Strin
g::NewSymbol("returnValue")); | |
387 if (returnValue.IsEmpty()) | |
388 return v8::Undefined(); | |
389 return returnValue; | |
390 } | |
391 | |
392 static void setUpDialog(DOMWindow* dialog, void* handler) | |
393 { | |
394 static_cast<DialogHandler*>(handler)->dialogCreated(dialog); | |
395 } | |
396 | |
397 void V8Window::showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Va
lue>& args) | |
398 { | |
399 DOMWindow* impl = V8Window::toNative(args.Holder()); | |
400 if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame())) | |
401 return; | |
402 | |
403 // FIXME: Handle exceptions properly. | |
404 String urlString = toWebCoreStringWithUndefinedOrNullCheck(args[0]); | |
405 DialogHandler handler(args[1]); | |
406 String dialogFeaturesString = toWebCoreStringWithUndefinedOrNullCheck(args[2
]); | |
407 | |
408 impl->showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(), fi
rstDOMWindow(), setUpDialog, &handler); | |
409 | |
410 v8SetReturnValue(args, handler.returnValue()); | |
411 } | |
412 | |
413 void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& args) | |
414 { | |
415 DOMWindow* impl = V8Window::toNative(args.Holder()); | |
416 if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame())) | |
417 return; | |
418 | |
419 // FIXME: Handle exceptions properly. | |
420 String urlString = toWebCoreStringWithUndefinedOrNullCheck(args[0]); | |
421 AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_b
lank" : AtomicString(toWebCoreString(args[1])); | |
422 String windowFeaturesString = toWebCoreStringWithUndefinedOrNullCheck(args[2
]); | |
423 | |
424 RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeat
uresString, activeDOMWindow(), firstDOMWindow()); | |
425 if (!openedWindow) | |
426 return; | |
427 | |
428 v8SetReturnValue(args, toV8Fast(openedWindow.release(), args, impl)); | |
429 } | |
430 | |
431 void V8Window::namedPropertyGetter(v8::Local<v8::String> name, const v8::Propert
yCallbackInfo<v8::Value>& info) | |
432 { | |
433 | |
434 DOMWindow* window = V8Window::toNative(info.Holder()); | |
435 if (!window) | |
436 return; | |
437 | |
438 Frame* frame = window->frame(); | |
439 // window is detached from a frame. | |
440 if (!frame) | |
441 return; | |
442 | |
443 // Search sub-frames. | |
444 AtomicString propName = toWebCoreAtomicString(name); | |
445 Frame* child = frame->tree()->scopedChild(propName); | |
446 if (child) { | |
447 v8SetReturnValue(info, toV8Fast(child->document()->domWindow(), info, wi
ndow)); | |
448 return; | |
449 } | |
450 | |
451 // Search IDL functions defined in the prototype | |
452 if (!info.Holder()->GetRealNamedProperty(name).IsEmpty()) | |
453 return; | |
454 | |
455 // Search named items in the document. | |
456 Document* doc = frame->document(); | |
457 | |
458 if (doc && doc->isHTMLDocument()) { | |
459 if (toHTMLDocument(doc)->hasNamedItem(propName.impl()) || doc->hasElemen
tWithId(propName.impl())) { | |
460 RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); | |
461 if (!items->isEmpty()) { | |
462 if (items->hasExactlyOneItem()) { | |
463 v8SetReturnValue(info, toV8Fast(items->item(0), info, window
)); | |
464 return; | |
465 } | |
466 v8SetReturnValue(info, toV8Fast(items.release(), info, window)); | |
467 return; | |
468 } | |
469 } | |
470 } | |
471 } | |
472 | |
473 | |
474 void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>&
args) | |
475 { | |
476 WindowSetTimeoutImpl(args, true); | |
477 } | |
478 | |
479 | |
480 void V8Window::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>
& args) | |
481 { | |
482 WindowSetTimeoutImpl(args, false); | |
483 } | |
484 | |
485 bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8
::Value> key, v8::AccessType type, v8::Local<v8::Value>) | |
486 { | |
487 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
488 v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window:
:GetTemplate(isolate, worldTypeInMainThread(isolate))); | |
489 if (window.IsEmpty()) | |
490 return false; // the frame is gone. | |
491 | |
492 DOMWindow* targetWindow = V8Window::toNative(window); | |
493 | |
494 ASSERT(targetWindow); | |
495 | |
496 Frame* target = targetWindow->frame(); | |
497 if (!target) | |
498 return false; | |
499 | |
500 // Notify the loader's client if the initial document has been accessed. | |
501 if (target->loader()->stateMachine()->isDisplayingInitialEmptyDocument()) | |
502 target->loader()->didAccessInitialDocument(); | |
503 | |
504 if (key->IsString()) { | |
505 DEFINE_STATIC_LOCAL(AtomicString, nameOfProtoProperty, ("__proto__", Ato
micString::ConstructFromLiteral)); | |
506 | |
507 String name = toWebCoreString(key); | |
508 Frame* childFrame = target->tree()->scopedChild(name); | |
509 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS | |
510 // because that would generate infinite recursion. | |
511 if (type == v8::ACCESS_HAS && childFrame) | |
512 return true; | |
513 // We need to explicitly compare against nameOfProtoProperty because | |
514 // V8's JSObject::LocalLookup finds __proto__ before | |
515 // interceptors and even when __proto__ isn't a "real named property". | |
516 v8::Handle<v8::String> keyString = key->ToString(); | |
517 if (type == v8::ACCESS_GET | |
518 && childFrame | |
519 && !host->HasRealNamedProperty(keyString) | |
520 && !window->HasRealNamedProperty(keyString) | |
521 && name != nameOfProtoProperty) | |
522 return true; | |
523 } | |
524 | |
525 return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurity
Error); | |
526 } | |
527 | |
528 bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t i
ndex, v8::AccessType type, v8::Local<v8::Value>) | |
529 { | |
530 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
531 v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window:
:GetTemplate(isolate, worldTypeInMainThread(isolate))); | |
532 if (window.IsEmpty()) | |
533 return false; | |
534 | |
535 DOMWindow* targetWindow = V8Window::toNative(window); | |
536 | |
537 ASSERT(targetWindow); | |
538 | |
539 Frame* target = targetWindow->frame(); | |
540 if (!target) | |
541 return false; | |
542 Frame* childFrame = target->tree()->scopedChild(index); | |
543 | |
544 // Notify the loader's client if the initial document has been accessed. | |
545 if (target->loader()->stateMachine()->isDisplayingInitialEmptyDocument()) | |
546 target->loader()->didAccessInitialDocument(); | |
547 | |
548 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS | |
549 // because that would generate infinite recursion. | |
550 if (type == v8::ACCESS_HAS && childFrame) | |
551 return true; | |
552 if (type == v8::ACCESS_GET && childFrame && !host->HasRealIndexedProperty(in
dex)) | |
553 return true; | |
554 | |
555 return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurity
Error); | |
556 } | |
557 | |
558 v8::Handle<v8::Value> toV8(DOMWindow* window, v8::Handle<v8::Object> creationCon
text, v8::Isolate* isolate) | |
559 { | |
560 // Notice that we explicitly ignore creationContext because the DOMWindow is
its own creationContext. | |
561 | |
562 if (!window) | |
563 return v8NullWithCheck(isolate); | |
564 // Initializes environment of a frame, and return the global object | |
565 // of the frame. | |
566 Frame* frame = window->frame(); | |
567 if (!frame) | |
568 return v8Undefined(); | |
569 | |
570 // Special case: Because of executeScriptInIsolatedWorld() one DOMWindow can
have | |
571 // multiple contexts and multiple global objects associated with it. When | |
572 // code running in one of those contexts accesses the window object, we | |
573 // want to return the global object associated with that context, not | |
574 // necessarily the first global object associated with that DOMWindow. | |
575 v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent(); | |
576 v8::Handle<v8::Object> currentGlobal = currentContext->Global(); | |
577 v8::Handle<v8::Object> windowWrapper = currentGlobal->FindInstanceInPrototyp
eChain(V8Window::GetTemplate(isolate, worldTypeInMainThread(isolate))); | |
578 if (!windowWrapper.IsEmpty()) { | |
579 if (V8Window::toNative(windowWrapper) == window) | |
580 return currentGlobal; | |
581 } | |
582 | |
583 // Otherwise, return the global object associated with this frame. | |
584 v8::Handle<v8::Context> context = frame->script()->currentWorldContext(); | |
585 if (context.IsEmpty()) | |
586 return v8Undefined(); | |
587 | |
588 v8::Handle<v8::Object> global = context->Global(); | |
589 ASSERT(!global.IsEmpty()); | |
590 return global; | |
591 } | |
592 | |
593 v8::Handle<v8::Value> toV8ForMainWorld(DOMWindow* window, v8::Handle<v8::Object>
creationContext, v8::Isolate* isolate) | |
594 { | |
595 return toV8(window, creationContext, isolate); | |
596 } | |
597 | |
598 } // namespace WebCore | |
OLD | NEW |