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