| 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 |