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 "bindings/core/v8/V8Window.h" | |
33 | |
34 #include "bindings/core/v8/V8HTMLCollection.h" | |
35 #include "bindings/core/v8/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/V8HiddenValue.h" | |
48 #include "core/dom/ExceptionCode.h" | |
49 #include "core/dom/MessagePort.h" | |
50 #include "core/html/HTMLCollection.h" | |
51 #include "core/html/HTMLDocument.h" | |
52 #include "core/inspector/ScriptCallStack.h" | |
53 #include "core/loader/FrameLoadRequest.h" | |
54 #include "core/loader/FrameLoader.h" | |
55 #include "core/frame/DOMTimer.h" | |
56 #include "core/frame/LocalDOMWindow.h" | |
57 #include "core/frame/DOMWindowTimers.h" | |
58 #include "core/frame/FrameView.h" | |
59 #include "core/frame/LocalFrame.h" | |
60 #include "core/frame/Settings.h" | |
61 #include "core/frame/csp/ContentSecurityPolicy.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 WebCore { | |
70 | |
71 // FIXME: There is a lot of duplication with SetTimeoutOrInterval() in V8WorkerG
lobalScopeCustom.cpp. | |
72 // We should refactor this. | |
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::toNative(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->fram
e(), 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::Functi
on>::Cast(function), paramCount, params.get(), info.GetIsolate())); | |
125 } else { | |
126 if (impl->document() && !impl->document()->contentSecurityPolicy()->allo
wEval()) { | |
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(maximumFireIn
terval); | |
146 } | |
147 | |
148 v8SetReturnValue(info, timerId); | |
149 } | |
150 | |
151 void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Val
ue>& info) | |
152 { | |
153 LocalFrame* frame = V8Window::toNative(info.Holder())->frame(); | |
154 ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Windo
w", info.Holder(), info.GetIsolate()); | |
155 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exc
eptionState)) { | |
156 exceptionState.throwIfNeeded(); | |
157 return; | |
158 } | |
159 | |
160 v8::Handle<v8::Value> jsEvent = V8HiddenValue::getHiddenValue(info.GetIsolat
e(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIs
olate())); | |
161 if (jsEvent.IsEmpty()) | |
162 return; | |
163 v8SetReturnValue(info, jsEvent); | |
164 } | |
165 | |
166 void V8Window::eventAttributeSetterCustom(v8::Local<v8::Value> value, const v8::
PropertyCallbackInfo<void>& info) | |
167 { | |
168 LocalFrame* frame = V8Window::toNative(info.Holder())->frame(); | |
169 ExceptionState exceptionState(ExceptionState::SetterContext, "event", "Windo
w", info.Holder(), info.GetIsolate()); | |
170 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exc
eptionState)) { | |
171 exceptionState.throwIfNeeded(); | |
172 return; | |
173 } | |
174 | |
175 V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder()->CreationCont
ext()->Global(), V8HiddenValue::event(info.GetIsolate()), value); | |
176 } | |
177 | |
178 void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo<
v8::Value>& info) | |
179 { | |
180 LocalDOMWindow* impl = V8Window::toNative(info.Holder()); | |
181 ExceptionState exceptionState(ExceptionState::GetterContext, "frame", "Windo
w", info.Holder(), info.GetIsolate()); | |
182 if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->frame
Element(), exceptionState)) { | |
183 v8SetReturnValueNull(info); | |
184 exceptionState.throwIfNeeded(); | |
185 return; | |
186 } | |
187 | |
188 // The wrapper for an <iframe> should get its prototype from the context of
the frame it's in, rather than its own frame. | |
189 // So, use its containing document as the creation context when wrapping. | |
190 v8::Handle<v8::Value> creationContext = toV8(&impl->frameElement()->document
(), info.Holder(), info.GetIsolate()); | |
191 RELEASE_ASSERT(!creationContext.IsEmpty()); | |
192 v8::Handle<v8::Value> wrapper = toV8(impl->frameElement(), v8::Handle<v8::Ob
ject>::Cast(creationContext), info.GetIsolate()); | |
193 v8SetReturnValue(info, wrapper); | |
194 } | |
195 | |
196 void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8:
:PropertyCallbackInfo<void>& info) | |
197 { | |
198 LocalDOMWindow* impl = V8Window::toNative(info.Holder()); | |
199 ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Wind
ow", info.Holder(), info.GetIsolate()); | |
200 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->fram
e(), exceptionState)) { | |
201 exceptionState.throwIfNeeded(); | |
202 return; | |
203 } | |
204 | |
205 // Opener can be shadowed if it is in the same domain. | |
206 // Have a special handling of null value to behave | |
207 // like Firefox. See bug http://b/1224887 & http://b/791706. | |
208 if (value->IsNull()) { | |
209 // impl->frame() cannot be null, | |
210 // otherwise, SameOrigin check would have failed. | |
211 ASSERT(impl->frame()); | |
212 impl->frame()->loader().setOpener(0); | |
213 } | |
214 | |
215 // Delete the accessor from this object. | |
216 info.Holder()->Delete(v8AtomicString(info.GetIsolate(), "opener")); | |
217 | |
218 // Put property on the front (this) object. | |
219 if (info.This()->IsObject()) | |
220 v8::Handle<v8::Object>::Cast(info.This())->Set(v8AtomicString(info.GetIs
olate(), "opener"), value); | |
221 } | |
222 | |
223 static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value) | |
224 { | |
225 if (value->IsString() || value->IsStringObject()) | |
226 return true; | |
227 return false; | |
228 } | |
229 | |
230 | |
231 void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>
& info) | |
232 { | |
233 // None of these need to be RefPtr because info and context are guaranteed | |
234 // to hold on to them. | |
235 LocalDOMWindow* window = V8Window::toNative(info.Holder()); | |
236 LocalDOMWindow* source = callingDOMWindow(info.GetIsolate()); | |
237 | |
238 ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage
", "Window", info.Holder(), info.GetIsolate()); | |
239 | |
240 // If called directly by WebCore we don't have a calling context. | |
241 if (!source) { | |
242 exceptionState.throwTypeError("No active calling context exists."); | |
243 exceptionState.throwIfNeeded(); | |
244 return; | |
245 } | |
246 | |
247 // This function has variable arguments and can be: | |
248 // Per current spec: | |
249 // postMessage(message, targetOrigin) | |
250 // postMessage(message, targetOrigin, {sequence of transferrables}) | |
251 // Legacy non-standard implementations in webkit allowed: | |
252 // postMessage(message, {sequence of transferrables}, targetOrigin); | |
253 MessagePortArray portArray; | |
254 ArrayBufferArray arrayBufferArray; | |
255 int targetOriginArgIndex = 1; | |
256 if (info.Length() > 2) { | |
257 int transferablesArgIndex = 2; | |
258 if (isLegacyTargetOriginDesignation(info[2])) { | |
259 targetOriginArgIndex = 2; | |
260 transferablesArgIndex = 1; | |
261 } | |
262 if (!SerializedScriptValue::extractTransferables(info[transferablesArgIn
dex], transferablesArgIndex, portArray, arrayBufferArray, exceptionState, info.G
etIsolate())) { | |
263 exceptionState.throwIfNeeded(); | |
264 return; | |
265 } | |
266 } | |
267 TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info
[targetOriginArgIndex]); | |
268 | |
269 RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0
], &portArray, &arrayBufferArray, exceptionState, info.GetIsolate()); | |
270 if (exceptionState.throwIfNeeded()) | |
271 return; | |
272 | |
273 window->postMessage(message.release(), &portArray, targetOrigin, source, exc
eptionState); | |
274 exceptionState.throwIfNeeded(); | |
275 } | |
276 | |
277 // FIXME(fqian): returning string is cheating, and we should | |
278 // fix this by calling toString function on the receiver. | |
279 // However, V8 implements toString in JavaScript, which requires | |
280 // switching context of receiver. I consider it is dangerous. | |
281 void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i
nfo) | |
282 { | |
283 v8::Handle<v8::Object> domWrapper = V8Window::findInstanceInPrototypeChain(i
nfo.This(), info.GetIsolate()); | |
284 if (domWrapper.IsEmpty()) { | |
285 v8SetReturnValue(info, info.This()->ObjectProtoToString()); | |
286 return; | |
287 } | |
288 v8SetReturnValue(info, domWrapper->ObjectProtoToString()); | |
289 } | |
290 | |
291 class DialogHandler { | |
292 public: | |
293 explicit DialogHandler(v8::Handle<v8::Value> dialogArguments, ScriptState* s
criptState) | |
294 : m_scriptState(scriptState) | |
295 , m_dialogArguments(dialogArguments) | |
296 { | |
297 } | |
298 | |
299 void dialogCreated(LocalDOMWindow*); | |
300 v8::Handle<v8::Value> returnValue() const; | |
301 | |
302 private: | |
303 RefPtr<ScriptState> m_scriptState; | |
304 RefPtr<ScriptState> m_scriptStateForDialogFrame; | |
305 v8::Handle<v8::Value> m_dialogArguments; | |
306 }; | |
307 | |
308 void DialogHandler::dialogCreated(LocalDOMWindow* dialogFrame) | |
309 { | |
310 if (m_dialogArguments.IsEmpty()) | |
311 return; | |
312 v8::Handle<v8::Context> context = toV8Context(dialogFrame->frame(), m_script
State->world()); | |
313 if (context.IsEmpty()) | |
314 return; | |
315 m_scriptStateForDialogFrame = ScriptState::from(context); | |
316 | |
317 ScriptState::Scope scope(m_scriptStateForDialogFrame.get()); | |
318 m_scriptStateForDialogFrame->context()->Global()->Set(v8AtomicString(m_scrip
tState->isolate(), "dialogArguments"), m_dialogArguments); | |
319 } | |
320 | |
321 v8::Handle<v8::Value> DialogHandler::returnValue() const | |
322 { | |
323 if (!m_scriptStateForDialogFrame) | |
324 return v8Undefined(); | |
325 ASSERT(!m_scriptStateForDialogFrame->contextIsEmpty()); | |
326 | |
327 v8::Isolate* isolate = m_scriptStateForDialogFrame->isolate(); | |
328 v8::EscapableHandleScope handleScope(isolate); | |
329 ScriptState::Scope scope(m_scriptStateForDialogFrame.get()); | |
330 v8::Local<v8::Value> returnValue = m_scriptStateForDialogFrame->context()->G
lobal()->Get(v8AtomicString(isolate, "returnValue")); | |
331 if (returnValue.IsEmpty()) | |
332 return v8Undefined(); | |
333 return handleScope.Escape(returnValue); | |
334 } | |
335 | |
336 static void setUpDialog(LocalDOMWindow* dialog, void* handler) | |
337 { | |
338 static_cast<DialogHandler*>(handler)->dialogCreated(dialog); | |
339 } | |
340 | |
341 void V8Window::showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Va
lue>& info) | |
342 { | |
343 LocalDOMWindow* impl = V8Window::toNative(info.Holder()); | |
344 ExceptionState exceptionState(ExceptionState::ExecutionContext, "showModalDi
alog", "Window", info.Holder(), info.GetIsolate()); | |
345 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->fram
e(), exceptionState)) { | |
346 exceptionState.throwIfNeeded(); | |
347 return; | |
348 } | |
349 | |
350 TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]
); | |
351 DialogHandler handler(info[1], ScriptState::current(info.GetIsolate())); | |
352 TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesStri
ng, info[2]); | |
353 | |
354 impl->showModalDialog(urlString, dialogFeaturesString, callingDOMWindow(info
.GetIsolate()), enteredDOMWindow(info.GetIsolate()), setUpDialog, &handler); | |
355 | |
356 v8SetReturnValue(info, handler.returnValue()); | |
357 } | |
358 | |
359 void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) | |
360 { | |
361 LocalDOMWindow* impl = V8Window::toNative(info.Holder()); | |
362 ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Win
dow", info.Holder(), info.GetIsolate()); | |
363 if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->fram
e(), exceptionState)) { | |
364 exceptionState.throwIfNeeded(); | |
365 return; | |
366 } | |
367 | |
368 TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]
); | |
369 AtomicString frameName; | |
370 if (info[1]->IsUndefined() || info[1]->IsNull()) { | |
371 frameName = "_blank"; | |
372 } else { | |
373 TOSTRING_VOID(V8StringResource<>, frameNameResource, info[1]); | |
374 frameName = frameNameResource; | |
375 } | |
376 TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesStri
ng, info[2]); | |
377 | |
378 RefPtrWillBeRawPtr<LocalDOMWindow> openedWindow = impl->open(urlString, fram
eName, windowFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWind
ow(info.GetIsolate())); | |
379 if (!openedWindow) | |
380 return; | |
381 | |
382 v8SetReturnValueFast(info, openedWindow.release(), impl); | |
383 } | |
384 | |
385 void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::P
ropertyCallbackInfo<v8::Value>& info) | |
386 { | |
387 | |
388 LocalDOMWindow* window = V8Window::toNative(info.Holder()); | |
389 if (!window) | |
390 return; | |
391 | |
392 LocalFrame* frame = window->frame(); | |
393 // window is detached from a frame. | |
394 if (!frame) | |
395 return; | |
396 | |
397 // Search sub-frames. | |
398 AtomicString propName = toCoreAtomicString(name); | |
399 Frame* child = frame->tree().scopedChild(propName); | |
400 if (child) { | |
401 v8SetReturnValueFast(info, child->domWindow(), window); | |
402 return; | |
403 } | |
404 | |
405 // Search IDL functions defined in the prototype | |
406 if (!info.Holder()->GetRealNamedProperty(name).IsEmpty()) | |
407 return; | |
408 | |
409 // Search named items in the document. | |
410 Document* doc = frame->document(); | |
411 | |
412 if (doc && doc->isHTMLDocument()) { | |
413 if (toHTMLDocument(doc)->hasNamedItem(propName) || doc->hasElementWithId
(propName.impl())) { | |
414 RefPtrWillBeRawPtr<HTMLCollection> items = doc->windowNamedItems(pro
pName); | |
415 if (!items->isEmpty()) { | |
416 if (items->hasExactlyOneItem()) { | |
417 v8SetReturnValueFast(info, items->item(0), window); | |
418 return; | |
419 } | |
420 v8SetReturnValueFast(info, items.release(), window); | |
421 return; | |
422 } | |
423 } | |
424 } | |
425 } | |
426 | |
427 | |
428 void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>&
info) | |
429 { | |
430 ExceptionState exceptionState(ExceptionState::ExecutionContext, "setTimeout"
, "Window", info.Holder(), info.GetIsolate()); | |
431 windowSetTimeoutImpl(info, true, exceptionState); | |
432 exceptionState.throwIfNeeded(); | |
433 } | |
434 | |
435 | |
436 void V8Window::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>
& info) | |
437 { | |
438 ExceptionState exceptionState(ExceptionState::ExecutionContext, "setInterval
", "Window", info.Holder(), info.GetIsolate()); | |
439 windowSetTimeoutImpl(info, false, exceptionState); | |
440 exceptionState.throwIfNeeded(); | |
441 } | |
442 | |
443 bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8
::Value> key, v8::AccessType type, v8::Local<v8::Value>) | |
444 { | |
445 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
446 v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host,
isolate); | |
447 if (window.IsEmpty()) | |
448 return false; // the frame is gone. | |
449 | |
450 LocalDOMWindow* targetWindow = V8Window::toNative(window); | |
451 | |
452 ASSERT(targetWindow); | |
453 | |
454 LocalFrame* target = targetWindow->frame(); | |
455 if (!target) | |
456 return false; | |
457 | |
458 // Notify the loader's client if the initial document has been accessed. | |
459 if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument()) | |
460 target->loader().didAccessInitialDocument(); | |
461 | |
462 if (key->IsString()) { | |
463 DEFINE_STATIC_LOCAL(const AtomicString, nameOfProtoProperty, ("__proto__
", AtomicString::ConstructFromLiteral)); | |
464 | |
465 AtomicString name = toCoreAtomicString(key.As<v8::String>()); | |
466 Frame* childFrame = target->tree().scopedChild(name); | |
467 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS | |
468 // because that would generate infinite recursion. | |
469 if (type == v8::ACCESS_HAS && childFrame) | |
470 return true; | |
471 // We need to explicitly compare against nameOfProtoProperty because | |
472 // V8's JSObject::LocalLookup finds __proto__ before | |
473 // interceptors and even when __proto__ isn't a "real named property". | |
474 v8::Handle<v8::String> keyString = key.As<v8::String>(); | |
475 if (type == v8::ACCESS_GET | |
476 && childFrame | |
477 && !host->HasRealNamedProperty(keyString) | |
478 && !window->HasRealNamedProperty(keyString) | |
479 && name != nameOfProtoProperty) | |
480 return true; | |
481 } | |
482 | |
483 return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotRepor
tSecurityError); | |
484 } | |
485 | |
486 bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t i
ndex, v8::AccessType type, v8::Local<v8::Value>) | |
487 { | |
488 v8::Isolate* isolate = v8::Isolate::GetCurrent(); | |
489 v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host,
isolate); | |
490 if (window.IsEmpty()) | |
491 return false; | |
492 | |
493 LocalDOMWindow* targetWindow = V8Window::toNative(window); | |
494 | |
495 ASSERT(targetWindow); | |
496 | |
497 LocalFrame* target = targetWindow->frame(); | |
498 if (!target) | |
499 return false; | |
500 | |
501 // Notify the loader's client if the initial document has been accessed. | |
502 if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument()) | |
503 target->loader().didAccessInitialDocument(); | |
504 | |
505 Frame* childFrame = target->tree().scopedChild(index); | |
506 | |
507 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS | |
508 // because that would generate infinite recursion. | |
509 if (type == v8::ACCESS_HAS && childFrame) | |
510 return true; | |
511 if (type == v8::ACCESS_GET | |
512 && childFrame | |
513 && !host->HasRealIndexedProperty(index) | |
514 && !window->HasRealIndexedProperty(index)) | |
515 return true; | |
516 | |
517 return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotRepor
tSecurityError); | |
518 } | |
519 | |
520 v8::Handle<v8::Value> toV8(LocalDOMWindow* window, v8::Handle<v8::Object> creati
onContext, v8::Isolate* isolate) | |
521 { | |
522 // Notice that we explicitly ignore creationContext because the LocalDOMWind
ow is its own creationContext. | |
523 | |
524 if (!window) | |
525 return v8::Null(isolate); | |
526 // Initializes environment of a frame, and return the global object | |
527 // of the frame. | |
528 LocalFrame* frame = window->frame(); | |
529 if (!frame) | |
530 return v8Undefined(); | |
531 | |
532 v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::curren
t(isolate)); | |
533 if (context.IsEmpty()) | |
534 return v8Undefined(); | |
535 | |
536 v8::Handle<v8::Object> global = context->Global(); | |
537 ASSERT(!global.IsEmpty()); | |
538 return global; | |
539 } | |
540 | |
541 } // namespace WebCore | |
OLD | NEW |