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