1 /* 2 * Copyright (C) 2009 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 "Chrome.h" 35 #include "ContentSecurityPolicy.h" 36 #include "DOMTimer.h" 37 #include "DOMWindow.h" 38 #include "ExceptionCode.h" 39 #include "Frame.h" 40 #include "FrameLoadRequest.h" 41 #include "FrameView.h" 42 #include "HTMLCollection.h" 43 #include "HTMLDocument.h" 44 #include "MediaPlayer.h" 45 #include "Page.h" 46 #include "PlatformScreen.h" 47 #include "ScheduledAction.h" 48 #include "ScriptSourceCode.h" 49 #include "SerializedScriptValue.h" 50 #include "Settings.h" 51 #include "SharedWorkerRepository.h" 52 #include "Storage.h" 53 #include "V8Binding.h" 54 #include "V8BindingMacros.h" 55 #include "V8BindingState.h" 56 #include "V8EventListener.h" 57 #include "V8GCForContextDispose.h" 58 #include "V8HiddenPropertyName.h" 59 #include "V8HTMLAudioElementConstructor.h" 60 #include "V8HTMLCollection.h" 61 #include "V8HTMLImageElementConstructor.h" 62 #include "V8HTMLOptionElementConstructor.h" 63 #include "V8MessagePortCustom.h" 64 #include "V8Node.h" 65 #include "V8Proxy.h" 66 #include "V8Utilities.h" 67 #if ENABLE(WEB_SOCKETS) 68 #include "WebSocket.h" 69 #endif 70 #include "WindowFeatures.h" 71 72 namespace WebCore { 73 74 v8::Handle<v8::Value> WindowSetTimeoutImpl(const v8::Arguments& args, bool singleShot) 75 { 76 int argumentCount = args.Length(); 77 78 if (argumentCount < 1) 79 return v8::Undefined(); 80 81 DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); 82 ScriptExecutionContext* scriptContext = static_cast<ScriptExecutionContext*>(imp->document()); 83 84 if (!scriptContext) { 85 V8Proxy::setDOMException(INVALID_ACCESS_ERR); 86 return v8::Undefined(); 87 } 88 89 v8::Handle<v8::Value> function = args[0]; 90 WTF::String functionString; 91 if (!function->IsFunction()) { 92 if (function->IsString()) 93 functionString = toWebCoreString(function); 94 else { 95 v8::Handle<v8::Value> v8String = function->ToString(); 96 97 // Bail out if string conversion failed. 98 if (v8String.IsEmpty()) 99 return v8::Undefined(); 100 101 functionString = toWebCoreString(v8String); 102 } 103 104 // Don't allow setting timeouts to run empty functions! 105 // (Bug 1009597) 106 if (functionString.length() == 0) 107 return v8::Undefined(); 108 } 109 110 int32_t timeout = 0; 111 if (argumentCount >= 2) 112 timeout = args[1]->Int32Value(); 113 114 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) 115 return v8::Undefined(); 116 117 int id; 118 if (function->IsFunction()) { 119 int paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; 120 v8::Local<v8::Value>* params = 0; 121 if (paramCount > 0) { 122 params = new v8::Local<v8::Value>[paramCount]; 123 for (int i = 0; i < paramCount; i++) 124 // parameters must be globalized 125 params[i] = args[i+2]; 126 } 127 128 // params is passed to action, and released in action's destructor 129 ScheduledAction* action = new ScheduledAction(V8Proxy::context(imp->frame()), v8::Handle<v8::Function>::Cast(function), paramCount, params); 130 131 delete[] params; 132 133 id = DOMTimer::install(scriptContext, action, timeout, singleShot); 134 } else { 135 if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval()) 136 return v8::Integer::New(0); 137 id = DOMTimer::install(scriptContext, new ScheduledAction(V8Proxy::context(imp->frame()), functionString), timeout, singleShot); 138 } 139 140 // Try to do the idle notification before the timeout expires to get better 141 // use of any idle time. Aim for the middle of the interval for simplicity. 142 if (timeout > 0) { 143 double maximumFireInterval = static_cast<double>(timeout) / 1000 / 2; 144 V8GCForContextDispose::instance().notifyIdleSooner(maximumFireInterval); 145 } 146 147 return v8::Integer::New(id); 148 } 149 150 v8::Handle<v8::Value> V8DOMWindow::eventAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 151 { 152 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), info.This()); 153 if (holder.IsEmpty()) 154 return v8::Undefined(); 155 156 Frame* frame = V8DOMWindow::toNative(holder)->frame(); 157 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true)) 158 return v8::Undefined(); 159 160 v8::Local<v8::Context> context = V8Proxy::context(frame); 161 if (context.IsEmpty()) 162 return v8::Undefined(); 163 164 v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(); 165 v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol); 166 if (jsEvent.IsEmpty()) 167 return v8::Undefined(); 168 return jsEvent; 169 } 170 171 void V8DOMWindow::eventAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 172 { 173 v8::Handle<v8::Object> holder = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), info.This()); 174 if (holder.IsEmpty()) 175 return; 176 177 Frame* frame = V8DOMWindow::toNative(holder)->frame(); 178 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), frame, true)) 179 return; 180 181 v8::Local<v8::Context> context = V8Proxy::context(frame); 182 if (context.IsEmpty()) 183 return; 184 185 v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(); 186 context->Global()->SetHiddenValue(eventSymbol, value); 187 } 188 189 void V8DOMWindow::locationAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 190 { 191 DOMWindow* imp = V8DOMWindow::toNative(info.Holder()); 192 State<V8Binding>* state = V8BindingState::Only(); 193 194 DOMWindow* activeWindow = state->activeWindow(); 195 if (!activeWindow) 196 return; 197 198 DOMWindow* firstWindow = state->firstWindow(); 199 if (!firstWindow) 200 return; 201 202 imp->setLocation(toWebCoreString(value), activeWindow, firstWindow); 203 } 204 205 void V8DOMWindow::openerAccessorSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) 206 { 207 DOMWindow* imp = V8DOMWindow::toNative(info.Holder()); 208 209 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) 210 return; 211 212 // Opener can be shadowed if it is in the same domain. 213 // Have a special handling of null value to behave 214 // like Firefox. See bug http://b/1224887 & http://b/791706. 215 if (value->IsNull()) { 216 // imp->frame() cannot be null, 217 // otherwise, SameOrigin check would have failed. 218 ASSERT(imp->frame()); 219 imp->frame()->loader()->setOpener(0); 220 } 221 222 // Delete the accessor from this object. 223 info.Holder()->Delete(name); 224 225 // Put property on the front (this) object. 226 info.This()->Set(name, value); 227 } 228 229 #if ENABLE(VIDEO) 230 231 v8::Handle<v8::Value> V8DOMWindow::AudioAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 232 { 233 DOMWindow* window = V8DOMWindow::toNative(info.Holder()); 234 return V8DOMWrapper::getConstructor(&V8HTMLAudioElementConstructor::info, window); 235 } 236 237 #endif 238 239 v8::Handle<v8::Value> V8DOMWindow::ImageAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 240 { 241 DOMWindow* window = V8DOMWindow::toNative(info.Holder()); 242 return V8DOMWrapper::getConstructor(&V8HTMLImageElementConstructor::info, window); 243 } 244 245 v8::Handle<v8::Value> V8DOMWindow::OptionAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 246 { 247 DOMWindow* window = V8DOMWindow::toNative(info.Holder()); 248 return V8DOMWrapper::getConstructor(&V8HTMLOptionElementConstructor::info, window); 249 } 250 251 v8::Handle<v8::Value> V8DOMWindow::addEventListenerCallback(const v8::Arguments& args) 252 { 253 INC_STATS("DOM.DOMWindow.addEventListener()"); 254 255 String eventType = toWebCoreString(args[0]); 256 bool useCapture = args[2]->BooleanValue(); 257 258 DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); 259 260 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) 261 return v8::Undefined(); 262 263 Document* doc = imp->document(); 264 265 if (!doc) 266 return v8::Undefined(); 267 268 // FIXME: Check if there is not enough arguments 269 V8Proxy* proxy = V8Proxy::retrieve(imp->frame()); 270 if (!proxy) 271 return v8::Undefined(); 272 273 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOrCreate); 274 275 if (listener) { 276 imp->addEventListener(eventType, listener, useCapture); 277 createHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex); 278 } 279 280 return v8::Undefined(); 281 } 282 283 284 v8::Handle<v8::Value> V8DOMWindow::removeEventListenerCallback(const v8::Arguments& args) 285 { 286 INC_STATS("DOM.DOMWindow.removeEventListener()"); 287 288 String eventType = toWebCoreString(args[0]); 289 bool useCapture = args[2]->BooleanValue(); 290 291 DOMWindow* imp = V8DOMWindow::toNative(args.Holder()); 292 293 if (!V8BindingSecurity::canAccessFrame(V8BindingState::Only(), imp->frame(), true)) 294 return v8::Undefined(); 295 296 Document* doc = imp->document(); 297 298 if (!doc) 299 return v8::Undefined(); 300 301 V8Proxy* proxy = V8Proxy::retrieve(imp->frame()); 302 if (!proxy) 303 return v8::Undefined(); 304 305 RefPtr<EventListener> listener = V8DOMWrapper::getEventListener(args[1], false, ListenerFindOnly); 306 307 if (listener) { 308 imp->removeEventListener(eventType, listener.get(), useCapture); 309 removeHiddenDependency(args.Holder(), args[1], eventListenerCacheIndex); 310 } 311 312 return v8::Undefined(); 313 } 314 315 v8::Handle<v8::Value> V8DOMWindow::postMessageCallback(const v8::Arguments& args) 316 { 317 INC_STATS("DOM.DOMWindow.postMessage()"); 318 DOMWindow* window = V8DOMWindow::toNative(args.Holder()); 319 320 DOMWindow* source = V8Proxy::retrieveFrameForCallingContext()->domWindow(); 321 ASSERT(source->frame()); 322 323 bool didThrow = false; 324 RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(args[0], didThrow); 325 if (didThrow) 326 return v8::Undefined(); 327 328 MessagePortArray portArray; 329 String targetOrigin; 330 331 // This function has variable arguments and can either be: 332 // postMessage(message, port, targetOrigin); 333 // or 334 // postMessage(message, targetOrigin); 335 v8::TryCatch tryCatch; 336 if (args.Length() > 2) { 337 if (!getMessagePortArray(args[1], portArray)) 338 return v8::Undefined(); 339 targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[2]); 340 } else { 341 targetOrigin = toWebCoreStringWithNullOrUndefinedCheck(args[1]); 342 } 343 344 if (tryCatch.HasCaught()) 345 return v8::Undefined(); 346 347 ExceptionCode ec = 0; 348 window->postMessage(message.release(), &portArray, targetOrigin, source, ec); 349 return throwError(ec); 350 } 351 352 // FIXME(fqian): returning string is cheating, and we should 353 // fix this by calling toString function on the receiver. 354 // However, V8 implements toString in JavaScript, which requires 355 // switching context of receiver. I consider it is dangerous. 356 v8::Handle<v8::Value> V8DOMWindow::toStringCallback(const v8::Arguments& args) 357 { 358 INC_STATS("DOM.DOMWindow.toString()"); 359 v8::Handle<v8::Object> domWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), args.This()); 360 if (domWrapper.IsEmpty()) 361 return args.This()->ObjectProtoToString(); 362 return domWrapper->ObjectProtoToString(); 363 } 364 365 v8::Handle<v8::Value> V8DOMWindow::releaseEventsCallback(const v8::Arguments& args) 366 { 367 INC_STATS("DOM.DOMWindow.nop()"); 368 return v8::Undefined(); 369 } 370 371 v8::Handle<v8::Value> V8DOMWindow::captureEventsCallback(const v8::Arguments& args) 372 { 373 INC_STATS("DOM.DOMWindow.nop()"); 374 return v8::Undefined(); 375 } 376 377 class DialogHandler { 378 public: 379 explicit DialogHandler(v8::Handle<v8::Value> dialogArguments) 380 : m_dialogArguments(dialogArguments) 381 { 382 } 383 384 void dialogCreated(DOMWindow*); 385 v8::Handle<v8::Value> returnValue() const; 386 387 private: 388 v8::Handle<v8::Value> m_dialogArguments; 389 v8::Handle<v8::Context> m_dialogContext; 390 }; 391 392 inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame) 393 { 394 m_dialogContext = V8Proxy::context(dialogFrame->frame()); 395 if (m_dialogContext.IsEmpty()) 396 return; 397 if (m_dialogArguments.IsEmpty()) 398 return; 399 v8::Context::Scope scope(m_dialogContext); 400 m_dialogContext->Global()->Set(v8::String::New("dialogArguments"), m_dialogArguments); 401 } 402 403 inline v8::Handle<v8::Value> DialogHandler::returnValue() const 404 { 405 if (m_dialogContext.IsEmpty()) 406 return v8::Undefined(); 407 v8::Context::Scope scope(m_dialogContext); 408 v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8::String::New("returnValue")); 409 if (returnValue.IsEmpty()) 410 return v8::Undefined(); 411 return returnValue; 412 } 413 414 static void setUpDialog(DOMWindow* dialog, void* handler) 415 { 416 static_cast<DialogHandler*>(handler)->dialogCreated(dialog); 417 } 418 419 v8::Handle<v8::Value> V8DOMWindow::showModalDialogCallback(const v8::Arguments& args) 420 { 421 INC_STATS("DOM.DOMWindow.showModalDialog()"); 422 DOMWindow* impl = V8DOMWindow::toNative(args.Holder()); 423 424 V8BindingState* state = V8BindingState::Only(); 425 426 DOMWindow* activeWindow = state->activeWindow(); 427 DOMWindow* firstWindow = state->firstWindow(); 428 429 // FIXME: Handle exceptions properly. 430 String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); 431 String dialogFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]); 432 433 DialogHandler handler(args[1]); 434 435 impl->showModalDialog(urlString, dialogFeaturesString, activeWindow, firstWindow, setUpDialog, &handler); 436 437 return handler.returnValue(); 438 } 439 440 v8::Handle<v8::Value> V8DOMWindow::openCallback(const v8::Arguments& args) 441 { 442 INC_STATS("DOM.DOMWindow.open()"); 443 DOMWindow* impl = V8DOMWindow::toNative(args.Holder()); 444 445 V8BindingState* state = V8BindingState::Only(); 446 447 DOMWindow* activeWindow = state->activeWindow(); 448 DOMWindow* firstWindow = state->firstWindow(); 449 450 // FIXME: Handle exceptions properly. 451 String urlString = toWebCoreStringWithNullOrUndefinedCheck(args[0]); 452 AtomicString frameName = (args[1]->IsUndefined() || args[1]->IsNull()) ? "_blank" : AtomicString(toWebCoreString(args[1])); 453 String windowFeaturesString = toWebCoreStringWithNullOrUndefinedCheck(args[2]); 454 455 RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeWindow, firstWindow); 456 if (!openedWindow) 457 return v8::Undefined(); 458 return toV8(openedWindow.release()); 459 } 460 461 v8::Handle<v8::Value> V8DOMWindow::indexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info) 462 { 463 INC_STATS("DOM.DOMWindow.IndexedPropertyGetter"); 464 465 DOMWindow* window = V8DOMWindow::toNative(info.Holder()); 466 if (!window) 467 return notHandledByInterceptor(); 468 469 Frame* frame = window->frame(); 470 if (!frame) 471 return notHandledByInterceptor(); 472 473 Frame* child = frame->tree()->child(index); 474 if (child) 475 return toV8(child->domWindow()); 476 477 return notHandledByInterceptor(); 478 } 479 480 481 v8::Handle<v8::Value> V8DOMWindow::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 482 { 483 INC_STATS("DOM.DOMWindow.NamedPropertyGetter"); 484 485 DOMWindow* window = V8DOMWindow::toNative(info.Holder()); 486 if (!window) 487 return notHandledByInterceptor(); 488 489 Frame* frame = window->frame(); 490 // window is detached from a frame. 491 if (!frame) 492 return notHandledByInterceptor(); 493 494 // Search sub-frames. 495 AtomicString propName = v8StringToAtomicWebCoreString(name); 496 Frame* child = frame->tree()->child(propName); 497 if (child) 498 return toV8(child->domWindow()); 499 500 // Search IDL functions defined in the prototype 501 v8::Handle<v8::Value> result = info.Holder()->GetRealNamedProperty(name); 502 if (!result.IsEmpty()) 503 return result; 504 505 // Search named items in the document. 506 Document* doc = frame->document(); 507 508 if (doc && doc->isHTMLDocument()) { 509 if (static_cast<HTMLDocument*>(doc)->hasNamedItem(propName.impl()) || doc->hasElementWithId(propName.impl())) { 510 RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); 511 if (items->length() >= 1) { 512 if (items->length() == 1) 513 return toV8(items->firstItem()); 514 return toV8(items.release()); 515 } 516 } 517 } 518 519 return notHandledByInterceptor(); 520 } 521 522 523 v8::Handle<v8::Value> V8DOMWindow::setTimeoutCallback(const v8::Arguments& args) 524 { 525 INC_STATS("DOM.DOMWindow.setTimeout()"); 526 return WindowSetTimeoutImpl(args, true); 527 } 528 529 530 v8::Handle<v8::Value> V8DOMWindow::setIntervalCallback(const v8::Arguments& args) 531 { 532 INC_STATS("DOM.DOMWindow.setInterval()"); 533 return WindowSetTimeoutImpl(args, false); 534 } 535 536 bool V8DOMWindow::namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) 537 { 538 v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); 539 if (window.IsEmpty()) 540 return false; // the frame is gone. 541 542 DOMWindow* targetWindow = V8DOMWindow::toNative(window); 543 544 ASSERT(targetWindow); 545 546 Frame* target = targetWindow->frame(); 547 if (!target) 548 return false; 549 550 if (key->IsString()) { 551 String name = toWebCoreString(key); 552 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS 553 // because that would generate infinite recursion. 554 if (type == v8::ACCESS_HAS && target->tree()->child(name)) 555 return true; 556 if (type == v8::ACCESS_GET && target->tree()->child(name) && !host->HasRealNamedProperty(key->ToString())) 557 return true; 558 } 559 560 return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false); 561 } 562 563 bool V8DOMWindow::indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) 564 { 565 v8::Handle<v8::Object> window = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), host); 566 if (window.IsEmpty()) 567 return false; 568 569 DOMWindow* targetWindow = V8DOMWindow::toNative(window); 570 571 ASSERT(targetWindow); 572 573 Frame* target = targetWindow->frame(); 574 if (!target) 575 return false; 576 577 // Notice that we can't call HasRealNamedProperty for ACCESS_HAS 578 // because that would generate infinite recursion. 579 if (type == v8::ACCESS_HAS && target->tree()->child(index)) 580 return true; 581 if (type == v8::ACCESS_GET && target->tree()->child(index) && !host->HasRealIndexedProperty(index)) 582 return true; 583 584 return V8BindingSecurity::canAccessFrame(V8BindingState::Only(), target, false); 585 } 586 587 v8::Handle<v8::Value> toV8(DOMWindow* window) 588 { 589 if (!window) 590 return v8::Null(); 591 // Initializes environment of a frame, and return the global object 592 // of the frame. 593 Frame* frame = window->frame(); 594 if (!frame) 595 return v8::Handle<v8::Object>(); 596 597 // Special case: Because of evaluateInIsolatedWorld() one DOMWindow can have 598 // multiple contexts and multiple global objects associated with it. When 599 // code running in one of those contexts accesses the window object, we 600 // want to return the global object associated with that context, not 601 // necessarily the first global object associated with that DOMWindow. 602 v8::Handle<v8::Context> currentContext = v8::Context::GetCurrent(); 603 v8::Handle<v8::Object> currentGlobal = currentContext->Global(); 604 v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), currentGlobal); 605 if (!windowWrapper.IsEmpty()) { 606 if (V8DOMWindow::toNative(windowWrapper) == window) 607 return currentGlobal; 608 } 609 610 // Otherwise, return the global object associated with this frame. 611 v8::Handle<v8::Context> context = V8Proxy::context(frame); 612 if (context.IsEmpty()) 613 return v8::Handle<v8::Object>(); 614 615 v8::Handle<v8::Object> global = context->Global(); 616 ASSERT(!global.IsEmpty()); 617 return global; 618 } 619 620 } // namespace WebCore 621