1 /* 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "core/frame/LocalDOMWindow.h" 29 30 #include "bindings/v8/ExceptionMessages.h" 31 #include "bindings/v8/ExceptionState.h" 32 #include "bindings/v8/ExceptionStatePlaceholder.h" 33 #include "bindings/v8/ScriptCallStackFactory.h" 34 #include "bindings/v8/ScriptController.h" 35 #include "bindings/v8/SerializedScriptValue.h" 36 #include "core/css/CSSComputedStyleDeclaration.h" 37 #include "core/css/CSSRuleList.h" 38 #include "core/css/DOMWindowCSS.h" 39 #include "core/css/MediaQueryList.h" 40 #include "core/css/MediaQueryMatcher.h" 41 #include "core/css/StyleMedia.h" 42 #include "core/css/resolver/StyleResolver.h" 43 #include "core/dom/ContextFeatures.h" 44 #include "core/dom/DOMImplementation.h" 45 #include "core/dom/Document.h" 46 #include "core/dom/Element.h" 47 #include "core/dom/ExceptionCode.h" 48 #include "core/dom/ExecutionContext.h" 49 #include "core/dom/NoEventDispatchAssertion.h" 50 #include "core/dom/RequestAnimationFrameCallback.h" 51 #include "core/editing/Editor.h" 52 #include "core/events/DOMWindowEventQueue.h" 53 #include "core/events/EventListener.h" 54 #include "core/events/HashChangeEvent.h" 55 #include "core/events/MessageEvent.h" 56 #include "core/events/PageTransitionEvent.h" 57 #include "core/events/PopStateEvent.h" 58 #include "core/frame/BarProp.h" 59 #include "core/frame/Console.h" 60 #include "core/frame/DOMPoint.h" 61 #include "core/frame/DOMWindowLifecycleNotifier.h" 62 #include "core/frame/EventHandlerRegistry.h" 63 #include "core/frame/FrameConsole.h" 64 #include "core/frame/FrameHost.h" 65 #include "core/frame/FrameView.h" 66 #include "core/frame/History.h" 67 #include "core/frame/LocalFrame.h" 68 #include "core/frame/Location.h" 69 #include "core/frame/Navigator.h" 70 #include "core/frame/Screen.h" 71 #include "core/frame/Settings.h" 72 #include "core/html/HTMLFrameOwnerElement.h" 73 #include "core/inspector/InspectorInstrumentation.h" 74 #include "core/inspector/InspectorTraceEvents.h" 75 #include "core/inspector/ScriptCallStack.h" 76 #include "core/loader/DocumentLoader.h" 77 #include "core/loader/FrameLoadRequest.h" 78 #include "core/loader/FrameLoader.h" 79 #include "core/loader/FrameLoaderClient.h" 80 #include "core/loader/MixedContentChecker.h" 81 #include "core/loader/SinkDocument.h" 82 #include "core/loader/appcache/ApplicationCache.h" 83 #include "core/page/BackForwardClient.h" 84 #include "core/page/Chrome.h" 85 #include "core/page/ChromeClient.h" 86 #include "core/page/CreateWindow.h" 87 #include "core/page/EventHandler.h" 88 #include "core/page/FrameTree.h" 89 #include "core/page/Page.h" 90 #include "core/page/WindowFeatures.h" 91 #include "core/page/WindowFocusAllowedIndicator.h" 92 #include "core/page/scrolling/ScrollingCoordinator.h" 93 #include "core/storage/Storage.h" 94 #include "core/storage/StorageArea.h" 95 #include "core/storage/StorageNamespace.h" 96 #include "core/timing/Performance.h" 97 #include "platform/PlatformScreen.h" 98 #include "platform/RuntimeEnabledFeatures.h" 99 #include "platform/UserGestureIndicator.h" 100 #include "platform/geometry/FloatRect.h" 101 #include "platform/graphics/media/MediaPlayer.h" 102 #include "platform/weborigin/KURL.h" 103 #include "platform/weborigin/SecurityOrigin.h" 104 #include "platform/weborigin/SecurityPolicy.h" 105 #include "public/platform/Platform.h" 106 #include "wtf/MainThread.h" 107 #include "wtf/MathExtras.h" 108 #include "wtf/text/WTFString.h" 109 #include <algorithm> 110 111 using std::min; 112 using std::max; 113 114 namespace WebCore { 115 116 class PostMessageTimer FINAL : public SuspendableTimer { 117 public: 118 PostMessageTimer(LocalDOMWindow& window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtrWillBeRawPtr<LocalDOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace, UserGestureToken* userGestureToken) 119 : SuspendableTimer(window.document()) 120 , m_window(&window) 121 , m_message(message) 122 , m_origin(sourceOrigin) 123 , m_source(source) 124 , m_channels(channels) 125 , m_targetOrigin(targetOrigin) 126 , m_stackTrace(stackTrace) 127 , m_userGestureToken(userGestureToken) 128 { 129 } 130 131 PassRefPtrWillBeRawPtr<MessageEvent> event() 132 { 133 return MessageEvent::create(m_channels.release(), m_message, m_origin, String(), m_source.get()); 134 135 } 136 SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); } 137 ScriptCallStack* stackTrace() const { return m_stackTrace.get(); } 138 UserGestureToken* userGestureToken() const { return m_userGestureToken.get(); } 139 140 private: 141 virtual void fired() OVERRIDE 142 { 143 m_window->postMessageTimerFired(this); 144 // This object is deleted now. 145 } 146 147 // FIXME: Oilpan: This raw pointer is safe because the PostMessageTimer is 148 // owned by the LocalDOMWindow. Ideally PostMessageTimer should be moved to 149 // the heap and use Member<LocalDOMWindow>. 150 LocalDOMWindow* m_window; 151 RefPtr<SerializedScriptValue> m_message; 152 String m_origin; 153 RefPtrWillBePersistent<LocalDOMWindow> m_source; 154 OwnPtr<MessagePortChannelArray> m_channels; 155 RefPtr<SecurityOrigin> m_targetOrigin; 156 RefPtrWillBePersistent<ScriptCallStack> m_stackTrace; 157 RefPtr<UserGestureToken> m_userGestureToken; 158 }; 159 160 static void disableSuddenTermination() 161 { 162 blink::Platform::current()->suddenTerminationChanged(false); 163 } 164 165 static void enableSuddenTermination() 166 { 167 blink::Platform::current()->suddenTerminationChanged(true); 168 } 169 170 typedef HashCountedSet<LocalDOMWindow*> DOMWindowSet; 171 172 static DOMWindowSet& windowsWithUnloadEventListeners() 173 { 174 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ()); 175 return windowsWithUnloadEventListeners; 176 } 177 178 static DOMWindowSet& windowsWithBeforeUnloadEventListeners() 179 { 180 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ()); 181 return windowsWithBeforeUnloadEventListeners; 182 } 183 184 static void addUnloadEventListener(LocalDOMWindow* domWindow) 185 { 186 DOMWindowSet& set = windowsWithUnloadEventListeners(); 187 if (set.isEmpty()) 188 disableSuddenTermination(); 189 set.add(domWindow); 190 } 191 192 static void removeUnloadEventListener(LocalDOMWindow* domWindow) 193 { 194 DOMWindowSet& set = windowsWithUnloadEventListeners(); 195 DOMWindowSet::iterator it = set.find(domWindow); 196 if (it == set.end()) 197 return; 198 set.remove(it); 199 if (set.isEmpty()) 200 enableSuddenTermination(); 201 } 202 203 static void removeAllUnloadEventListeners(LocalDOMWindow* domWindow) 204 { 205 DOMWindowSet& set = windowsWithUnloadEventListeners(); 206 DOMWindowSet::iterator it = set.find(domWindow); 207 if (it == set.end()) 208 return; 209 set.removeAll(it); 210 if (set.isEmpty()) 211 enableSuddenTermination(); 212 } 213 214 static void addBeforeUnloadEventListener(LocalDOMWindow* domWindow) 215 { 216 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); 217 if (set.isEmpty()) 218 disableSuddenTermination(); 219 set.add(domWindow); 220 } 221 222 static void removeBeforeUnloadEventListener(LocalDOMWindow* domWindow) 223 { 224 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); 225 DOMWindowSet::iterator it = set.find(domWindow); 226 if (it == set.end()) 227 return; 228 set.remove(it); 229 if (set.isEmpty()) 230 enableSuddenTermination(); 231 } 232 233 static void removeAllBeforeUnloadEventListeners(LocalDOMWindow* domWindow) 234 { 235 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners(); 236 DOMWindowSet::iterator it = set.find(domWindow); 237 if (it == set.end()) 238 return; 239 set.removeAll(it); 240 if (set.isEmpty()) 241 enableSuddenTermination(); 242 } 243 244 static bool allowsBeforeUnloadListeners(LocalDOMWindow* window) 245 { 246 ASSERT_ARG(window, window); 247 LocalFrame* frame = window->frame(); 248 if (!frame) 249 return false; 250 return frame->isMainFrame(); 251 } 252 253 unsigned LocalDOMWindow::pendingUnloadEventListeners() const 254 { 255 return windowsWithUnloadEventListeners().count(const_cast<LocalDOMWindow*>(this)); 256 } 257 258 // This function: 259 // 1) Validates the pending changes are not changing any value to NaN; in that case keep original value. 260 // 2) Constrains the window rect to the minimum window size and no bigger than the float rect's dimensions. 261 // 3) Constrains the window rect to within the top and left boundaries of the available screen rect. 262 // 4) Constrains the window rect to within the bottom and right boundaries of the available screen rect. 263 // 5) Translate the window rect coordinates to be within the coordinate space of the screen. 264 FloatRect LocalDOMWindow::adjustWindowRect(LocalFrame& frame, const FloatRect& pendingChanges) 265 { 266 FrameHost* host = frame.host(); 267 ASSERT(host); 268 269 FloatRect screen = screenAvailableRect(frame.view()); 270 FloatRect window = host->chrome().windowRect(); 271 272 // Make sure we're in a valid state before adjusting dimensions. 273 ASSERT(std::isfinite(screen.x())); 274 ASSERT(std::isfinite(screen.y())); 275 ASSERT(std::isfinite(screen.width())); 276 ASSERT(std::isfinite(screen.height())); 277 ASSERT(std::isfinite(window.x())); 278 ASSERT(std::isfinite(window.y())); 279 ASSERT(std::isfinite(window.width())); 280 ASSERT(std::isfinite(window.height())); 281 282 // Update window values if new requested values are not NaN. 283 if (!std::isnan(pendingChanges.x())) 284 window.setX(pendingChanges.x()); 285 if (!std::isnan(pendingChanges.y())) 286 window.setY(pendingChanges.y()); 287 if (!std::isnan(pendingChanges.width())) 288 window.setWidth(pendingChanges.width()); 289 if (!std::isnan(pendingChanges.height())) 290 window.setHeight(pendingChanges.height()); 291 292 FloatSize minimumSize = host->chrome().client().minimumWindowSize(); 293 // Let size 0 pass through, since that indicates default size, not minimum size. 294 if (window.width()) 295 window.setWidth(min(max(minimumSize.width(), window.width()), screen.width())); 296 if (window.height()) 297 window.setHeight(min(max(minimumSize.height(), window.height()), screen.height())); 298 299 // Constrain the window position within the valid screen area. 300 window.setX(max(screen.x(), min(window.x(), screen.maxX() - window.width()))); 301 window.setY(max(screen.y(), min(window.y(), screen.maxY() - window.height()))); 302 303 return window; 304 } 305 306 bool LocalDOMWindow::allowPopUp(LocalFrame& firstFrame) 307 { 308 if (UserGestureIndicator::processingUserGesture()) 309 return true; 310 311 Settings* settings = firstFrame.settings(); 312 return settings && settings->javaScriptCanOpenWindowsAutomatically(); 313 } 314 315 bool LocalDOMWindow::allowPopUp() 316 { 317 return m_frame && allowPopUp(*m_frame); 318 } 319 320 bool LocalDOMWindow::canShowModalDialogNow(const LocalFrame* frame) 321 { 322 if (!frame) 323 return false; 324 FrameHost* host = frame->host(); 325 if (!host) 326 return false; 327 return host->chrome().canRunModalNow(); 328 } 329 330 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame) 331 : FrameDestructionObserver(&frame) 332 , m_shouldPrintWhenFinishedLoading(false) 333 #if ASSERT_ENABLED 334 , m_hasBeenReset(false) 335 #endif 336 { 337 ScriptWrappable::init(this); 338 } 339 340 void LocalDOMWindow::clearDocument() 341 { 342 if (!m_document) 343 return; 344 345 if (m_document->isActive()) { 346 // FIXME: We don't call willRemove here. Why is that OK? 347 // This detach() call is also mostly redundant. Most of the calls to 348 // this function come via DocumentLoader::createWriterFor, which 349 // always detaches the previous Document first. Only XSLTProcessor 350 // depends on this detach() call, so it seems like there's some room 351 // for cleanup. 352 m_document->detach(); 353 } 354 355 // FIXME: This should be part of ActiveDOMObject shutdown 356 clearEventQueue(); 357 358 m_document->clearDOMWindow(); 359 m_document = nullptr; 360 } 361 362 void LocalDOMWindow::clearEventQueue() 363 { 364 if (!m_eventQueue) 365 return; 366 m_eventQueue->close(); 367 m_eventQueue.clear(); 368 } 369 370 void LocalDOMWindow::acceptLanguagesChanged() 371 { 372 if (m_navigator) 373 m_navigator->setLanguagesChanged(); 374 375 dispatchEvent(Event::create(EventTypeNames::languagechange)); 376 } 377 378 PassRefPtrWillBeRawPtr<Document> LocalDOMWindow::createDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML) 379 { 380 RefPtrWillBeRawPtr<Document> document = nullptr; 381 if (forceXHTML) { 382 // This is a hack for XSLTProcessor. See XSLTProcessor::createDocumentFromSource(). 383 document = Document::create(init); 384 } else { 385 document = DOMImplementation::createDocument(mimeType, init, init.frame() ? init.frame()->inViewSourceMode() : false); 386 if (document->isPluginDocument() && document->isSandboxed(SandboxPlugins)) 387 document = SinkDocument::create(init); 388 } 389 390 return document.release(); 391 } 392 393 PassRefPtrWillBeRawPtr<Document> LocalDOMWindow::installNewDocument(const String& mimeType, const DocumentInit& init, bool forceXHTML) 394 { 395 ASSERT(init.frame() == m_frame); 396 397 clearDocument(); 398 399 m_document = createDocument(mimeType, init, forceXHTML); 400 m_eventQueue = DOMWindowEventQueue::create(m_document.get()); 401 m_document->attach(); 402 403 if (!m_frame) { 404 // FIXME: Oilpan: Remove .get() when m_document becomes Member<>. 405 return m_document.get(); 406 } 407 408 m_frame->script().updateDocument(); 409 m_document->updateViewportDescription(); 410 411 if (m_frame->page() && m_frame->view()) { 412 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) { 413 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_frame->view(), HorizontalScrollbar); 414 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_frame->view(), VerticalScrollbar); 415 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_frame->view()); 416 } 417 } 418 419 m_frame->selection().updateSecureKeyboardEntryIfActive(); 420 421 if (m_frame->isMainFrame()) { 422 if (m_document->hasTouchEventHandlers()) 423 m_frame->host()->chrome().client().needTouchEvents(true); 424 } 425 426 // FIXME: Oilpan: Remove .get() when m_document becomes Member<>. 427 return m_document.get(); 428 } 429 430 EventQueue* LocalDOMWindow::eventQueue() const 431 { 432 return m_eventQueue.get(); 433 } 434 435 void LocalDOMWindow::enqueueWindowEvent(PassRefPtrWillBeRawPtr<Event> event) 436 { 437 if (!m_eventQueue) 438 return; 439 event->setTarget(this); 440 m_eventQueue->enqueueEvent(event); 441 } 442 443 void LocalDOMWindow::enqueueDocumentEvent(PassRefPtrWillBeRawPtr<Event> event) 444 { 445 if (!m_eventQueue) 446 return; 447 event->setTarget(m_document.get()); 448 m_eventQueue->enqueueEvent(event); 449 } 450 451 void LocalDOMWindow::dispatchWindowLoadEvent() 452 { 453 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 454 dispatchLoadEvent(); 455 } 456 457 void LocalDOMWindow::documentWasClosed() 458 { 459 dispatchWindowLoadEvent(); 460 enqueuePageshowEvent(PageshowEventNotPersisted); 461 if (m_pendingStateObject) 462 enqueuePopstateEvent(m_pendingStateObject.release()); 463 } 464 465 void LocalDOMWindow::enqueuePageshowEvent(PageshowEventPersistence persisted) 466 { 467 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36334 Pageshow event needs to fire asynchronously. 468 // As per spec pageshow must be triggered asynchronously. 469 // However to be compatible with other browsers blink fires pageshow synchronously. 470 dispatchEvent(PageTransitionEvent::create(EventTypeNames::pageshow, persisted), m_document.get()); 471 } 472 473 void LocalDOMWindow::enqueueHashchangeEvent(const String& oldURL, const String& newURL) 474 { 475 enqueueWindowEvent(HashChangeEvent::create(oldURL, newURL)); 476 } 477 478 void LocalDOMWindow::enqueuePopstateEvent(PassRefPtr<SerializedScriptValue> stateObject) 479 { 480 if (!ContextFeatures::pushStateEnabled(document())) 481 return; 482 483 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=36202 Popstate event needs to fire asynchronously 484 dispatchEvent(PopStateEvent::create(stateObject, &history())); 485 } 486 487 void LocalDOMWindow::statePopped(PassRefPtr<SerializedScriptValue> stateObject) 488 { 489 if (!frame()) 490 return; 491 492 // Per step 11 of section 6.5.9 (history traversal) of the HTML5 spec, we 493 // defer firing of popstate until we're in the complete state. 494 if (document()->isLoadCompleted()) 495 enqueuePopstateEvent(stateObject); 496 else 497 m_pendingStateObject = stateObject; 498 } 499 500 LocalDOMWindow::~LocalDOMWindow() 501 { 502 ASSERT(m_hasBeenReset); 503 reset(); 504 505 #if ENABLE(OILPAN) 506 // Oilpan: the frame host and document objects are 507 // also garbage collected; cannot notify these 508 // when removing event listeners. 509 removeAllEventListenersInternal(DoNotBroadcastListenerRemoval); 510 511 // Cleared when detaching document. 512 ASSERT(!m_eventQueue); 513 #else 514 removeAllEventListenersInternal(DoBroadcastListenerRemoval); 515 516 ASSERT(m_document->isStopped()); 517 clearDocument(); 518 #endif 519 } 520 521 const AtomicString& LocalDOMWindow::interfaceName() const 522 { 523 return EventTargetNames::LocalDOMWindow; 524 } 525 526 ExecutionContext* LocalDOMWindow::executionContext() const 527 { 528 return m_document.get(); 529 } 530 531 LocalDOMWindow* LocalDOMWindow::toDOMWindow() 532 { 533 return this; 534 } 535 536 PassRefPtrWillBeRawPtr<MediaQueryList> LocalDOMWindow::matchMedia(const String& media) 537 { 538 return document() ? document()->mediaQueryMatcher().matchMedia(media) : nullptr; 539 } 540 541 Page* LocalDOMWindow::page() 542 { 543 return frame() ? frame()->page() : 0; 544 } 545 546 void LocalDOMWindow::frameDestroyed() 547 { 548 FrameDestructionObserver::frameDestroyed(); 549 reset(); 550 } 551 552 void LocalDOMWindow::willDetachFrameHost() 553 { 554 m_frame->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); 555 InspectorInstrumentation::frameWindowDiscarded(m_frame, this); 556 } 557 558 void LocalDOMWindow::willDestroyDocumentInFrame() 559 { 560 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may 561 // unregister themselves from the LocalDOMWindow as a result of the call to willDestroyGlobalObjectInFrame. 562 Vector<DOMWindowProperty*> properties; 563 copyToVector(m_properties, properties); 564 for (size_t i = 0; i < properties.size(); ++i) 565 properties[i]->willDestroyGlobalObjectInFrame(); 566 } 567 568 void LocalDOMWindow::willDetachDocumentFromFrame() 569 { 570 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may 571 // unregister themselves from the LocalDOMWindow as a result of the call to willDetachGlobalObjectFromFrame. 572 Vector<DOMWindowProperty*> properties; 573 copyToVector(m_properties, properties); 574 for (size_t i = 0; i < properties.size(); ++i) 575 properties[i]->willDetachGlobalObjectFromFrame(); 576 } 577 578 void LocalDOMWindow::registerProperty(DOMWindowProperty* property) 579 { 580 m_properties.add(property); 581 } 582 583 void LocalDOMWindow::unregisterProperty(DOMWindowProperty* property) 584 { 585 m_properties.remove(property); 586 } 587 588 void LocalDOMWindow::reset() 589 { 590 willDestroyDocumentInFrame(); 591 resetDOMWindowProperties(); 592 } 593 594 void LocalDOMWindow::resetDOMWindowProperties() 595 { 596 m_properties.clear(); 597 598 m_screen = nullptr; 599 m_history = nullptr; 600 m_locationbar = nullptr; 601 m_menubar = nullptr; 602 m_personalbar = nullptr; 603 m_scrollbars = nullptr; 604 m_statusbar = nullptr; 605 m_toolbar = nullptr; 606 m_console = nullptr; 607 m_navigator = nullptr; 608 m_performance = nullptr; 609 m_location = nullptr; 610 m_media = nullptr; 611 m_sessionStorage = nullptr; 612 m_localStorage = nullptr; 613 m_applicationCache = nullptr; 614 #if ASSERT_ENABLED 615 m_hasBeenReset = true; 616 #endif 617 } 618 619 bool LocalDOMWindow::isCurrentlyDisplayedInFrame() const 620 { 621 return m_frame && m_frame->domWindow() == this && m_frame->host(); 622 } 623 624 int LocalDOMWindow::orientation() const 625 { 626 ASSERT(RuntimeEnabledFeatures::orientationEventEnabled()); 627 628 if (!m_frame) 629 return 0; 630 631 int orientation = screenOrientationAngle(m_frame->view()); 632 // For backward compatibility, we want to return a value in the range of 633 // [-90; 180] instead of [0; 360[ because window.orientation used to behave 634 // like that in WebKit (this is a WebKit proprietary API). 635 if (orientation == 270) 636 return -90; 637 return orientation; 638 } 639 640 Screen& LocalDOMWindow::screen() const 641 { 642 if (!m_screen) 643 m_screen = Screen::create(m_frame); 644 return *m_screen; 645 } 646 647 History& LocalDOMWindow::history() const 648 { 649 if (!m_history) 650 m_history = History::create(m_frame); 651 return *m_history; 652 } 653 654 BarProp& LocalDOMWindow::locationbar() const 655 { 656 if (!m_locationbar) 657 m_locationbar = BarProp::create(m_frame, BarProp::Locationbar); 658 return *m_locationbar; 659 } 660 661 BarProp& LocalDOMWindow::menubar() const 662 { 663 if (!m_menubar) 664 m_menubar = BarProp::create(m_frame, BarProp::Menubar); 665 return *m_menubar; 666 } 667 668 BarProp& LocalDOMWindow::personalbar() const 669 { 670 if (!m_personalbar) 671 m_personalbar = BarProp::create(m_frame, BarProp::Personalbar); 672 return *m_personalbar; 673 } 674 675 BarProp& LocalDOMWindow::scrollbars() const 676 { 677 if (!m_scrollbars) 678 m_scrollbars = BarProp::create(m_frame, BarProp::Scrollbars); 679 return *m_scrollbars; 680 } 681 682 BarProp& LocalDOMWindow::statusbar() const 683 { 684 if (!m_statusbar) 685 m_statusbar = BarProp::create(m_frame, BarProp::Statusbar); 686 return *m_statusbar; 687 } 688 689 BarProp& LocalDOMWindow::toolbar() const 690 { 691 if (!m_toolbar) 692 m_toolbar = BarProp::create(m_frame, BarProp::Toolbar); 693 return *m_toolbar; 694 } 695 696 Console& LocalDOMWindow::console() const 697 { 698 if (!m_console) 699 m_console = Console::create(m_frame); 700 return *m_console; 701 } 702 703 FrameConsole* LocalDOMWindow::frameConsole() const 704 { 705 if (!isCurrentlyDisplayedInFrame()) 706 return 0; 707 return &m_frame->console(); 708 } 709 710 ApplicationCache* LocalDOMWindow::applicationCache() const 711 { 712 if (!isCurrentlyDisplayedInFrame()) 713 return 0; 714 if (!m_applicationCache) 715 m_applicationCache = ApplicationCache::create(m_frame); 716 return m_applicationCache.get(); 717 } 718 719 Navigator& LocalDOMWindow::navigator() const 720 { 721 if (!m_navigator) 722 m_navigator = Navigator::create(m_frame); 723 return *m_navigator; 724 } 725 726 Performance& LocalDOMWindow::performance() const 727 { 728 if (!m_performance) 729 m_performance = Performance::create(m_frame); 730 return *m_performance; 731 } 732 733 Location& LocalDOMWindow::location() const 734 { 735 if (!m_location) 736 m_location = Location::create(m_frame); 737 return *m_location; 738 } 739 740 Storage* LocalDOMWindow::sessionStorage(ExceptionState& exceptionState) const 741 { 742 if (!isCurrentlyDisplayedInFrame()) 743 return 0; 744 745 Document* document = this->document(); 746 if (!document) 747 return 0; 748 749 String accessDeniedMessage = "Access is denied for this document."; 750 if (!document->securityOrigin()->canAccessLocalStorage()) { 751 if (document->isSandboxed(SandboxOrigin)) 752 exceptionState.throwSecurityError("The document is sandboxed and lacks the 'allow-same-origin' flag."); 753 else if (document->url().protocolIs("data")) 754 exceptionState.throwSecurityError("Storage is disabled inside 'data:' URLs."); 755 else 756 exceptionState.throwSecurityError(accessDeniedMessage); 757 return 0; 758 } 759 760 if (m_sessionStorage) { 761 if (!m_sessionStorage->area()->canAccessStorage(m_frame)) { 762 exceptionState.throwSecurityError(accessDeniedMessage); 763 return 0; 764 } 765 return m_sessionStorage.get(); 766 } 767 768 Page* page = document->page(); 769 if (!page) 770 return 0; 771 772 OwnPtrWillBeRawPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin()); 773 if (!storageArea->canAccessStorage(m_frame)) { 774 exceptionState.throwSecurityError(accessDeniedMessage); 775 return 0; 776 } 777 778 m_sessionStorage = Storage::create(m_frame, storageArea.release()); 779 return m_sessionStorage.get(); 780 } 781 782 Storage* LocalDOMWindow::localStorage(ExceptionState& exceptionState) const 783 { 784 if (!isCurrentlyDisplayedInFrame()) 785 return 0; 786 787 Document* document = this->document(); 788 if (!document) 789 return 0; 790 791 String accessDeniedMessage = "Access is denied for this document."; 792 if (!document->securityOrigin()->canAccessLocalStorage()) { 793 if (document->isSandboxed(SandboxOrigin)) 794 exceptionState.throwSecurityError("The document is sandboxed and lacks the 'allow-same-origin' flag."); 795 else if (document->url().protocolIs("data")) 796 exceptionState.throwSecurityError("Storage is disabled inside 'data:' URLs."); 797 else 798 exceptionState.throwSecurityError(accessDeniedMessage); 799 return 0; 800 } 801 802 if (m_localStorage) { 803 if (!m_localStorage->area()->canAccessStorage(m_frame)) { 804 exceptionState.throwSecurityError(accessDeniedMessage); 805 return 0; 806 } 807 return m_localStorage.get(); 808 } 809 810 // FIXME: Seems this check should be much higher? 811 FrameHost* host = document->frameHost(); 812 if (!host || !host->settings().localStorageEnabled()) 813 return 0; 814 815 OwnPtrWillBeRawPtr<StorageArea> storageArea = StorageNamespace::localStorageArea(document->securityOrigin()); 816 if (!storageArea->canAccessStorage(m_frame)) { 817 exceptionState.throwSecurityError(accessDeniedMessage); 818 return 0; 819 } 820 821 m_localStorage = Storage::create(m_frame, storageArea.release()); 822 return m_localStorage.get(); 823 } 824 825 void LocalDOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, LocalDOMWindow* source, ExceptionState& exceptionState) 826 { 827 if (!isCurrentlyDisplayedInFrame()) 828 return; 829 830 Document* sourceDocument = source->document(); 831 832 // Compute the target origin. We need to do this synchronously in order 833 // to generate the SyntaxError exception correctly. 834 RefPtr<SecurityOrigin> target; 835 if (targetOrigin == "/") { 836 if (!sourceDocument) 837 return; 838 target = sourceDocument->securityOrigin(); 839 } else if (targetOrigin != "*") { 840 target = SecurityOrigin::createFromString(targetOrigin); 841 // It doesn't make sense target a postMessage at a unique origin 842 // because there's no way to represent a unique origin in a string. 843 if (target->isUnique()) { 844 exceptionState.throwDOMException(SyntaxError, "Invalid target origin '" + targetOrigin + "' in a call to 'postMessage'."); 845 return; 846 } 847 } 848 849 OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, exceptionState); 850 if (exceptionState.hadException()) 851 return; 852 853 // Capture the source of the message. We need to do this synchronously 854 // in order to capture the source of the message correctly. 855 if (!sourceDocument) 856 return; 857 String sourceOrigin = sourceDocument->securityOrigin()->toString(); 858 859 if (MixedContentChecker::isMixedContent(sourceDocument->securityOrigin(), document()->url())) 860 UseCounter::count(document(), UseCounter::PostMessageFromSecureToInsecure); 861 else if (MixedContentChecker::isMixedContent(document()->securityOrigin(), sourceDocument->url())) 862 UseCounter::count(document(), UseCounter::PostMessageFromInsecureToSecure); 863 864 // Capture stack trace only when inspector front-end is loaded as it may be time consuming. 865 RefPtrWillBeRawPtr<ScriptCallStack> stackTrace = nullptr; 866 if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument)) 867 stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true); 868 869 // Schedule the message. 870 OwnPtr<PostMessageTimer> timer = adoptPtr(new PostMessageTimer(*this, message, sourceOrigin, source, channels.release(), target.get(), stackTrace.release(), UserGestureIndicator::currentToken())); 871 timer->startOneShot(0, FROM_HERE); 872 timer->suspendIfNeeded(); 873 m_postMessageTimers.add(timer.release()); 874 } 875 876 void LocalDOMWindow::postMessageTimerFired(PostMessageTimer* timer) 877 { 878 if (!isCurrentlyDisplayedInFrame()) { 879 m_postMessageTimers.remove(timer); 880 return; 881 } 882 883 RefPtrWillBeRawPtr<MessageEvent> event = timer->event(); 884 885 // Give the embedder a chance to intercept this postMessage because this 886 // LocalDOMWindow might be a proxy for another in browsers that support 887 // postMessage calls across WebKit instances. 888 if (m_frame->loader().client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get())) { 889 m_postMessageTimers.remove(timer); 890 return; 891 } 892 893 UserGestureIndicator gestureIndicator(timer->userGestureToken()); 894 895 event->entangleMessagePorts(document()); 896 dispatchMessageEventWithOriginCheck(timer->targetOrigin(), event, timer->stackTrace()); 897 m_postMessageTimers.remove(timer); 898 } 899 900 void LocalDOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtrWillBeRawPtr<Event> event, PassRefPtrWillBeRawPtr<ScriptCallStack> stackTrace) 901 { 902 if (intendedTargetOrigin) { 903 // Check target origin now since the target document may have changed since the timer was scheduled. 904 if (!intendedTargetOrigin->isSameSchemeHostPort(document()->securityOrigin())) { 905 String message = ExceptionMessages::failedToExecute("postMessage", "DOMWindow", "The target origin provided ('" + intendedTargetOrigin->toString() + "') does not match the recipient window's origin ('" + document()->securityOrigin()->toString() + "')."); 906 frameConsole()->addMessage(SecurityMessageSource, ErrorMessageLevel, message, stackTrace); 907 return; 908 } 909 } 910 911 dispatchEvent(event); 912 } 913 914 DOMSelection* LocalDOMWindow::getSelection() 915 { 916 if (!isCurrentlyDisplayedInFrame() || !m_frame) 917 return 0; 918 919 return m_frame->document()->getSelection(); 920 } 921 922 Element* LocalDOMWindow::frameElement() const 923 { 924 if (!m_frame) 925 return 0; 926 927 // The bindings security check should ensure we're same origin... 928 ASSERT(!m_frame->owner() || m_frame->owner()->isLocal()); 929 return m_frame->deprecatedLocalOwner(); 930 } 931 932 void LocalDOMWindow::focus(ExecutionContext* context) 933 { 934 if (!m_frame) 935 return; 936 937 FrameHost* host = m_frame->host(); 938 if (!host) 939 return; 940 941 bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed(); 942 if (context) { 943 ASSERT(isMainThread()); 944 Document* activeDocument = toDocument(context); 945 if (opener() && opener() != this && activeDocument->domWindow() == opener()) 946 allowFocus = true; 947 } 948 949 // If we're a top level window, bring the window to the front. 950 if (m_frame->isMainFrame() && allowFocus) 951 host->chrome().focus(); 952 953 if (!m_frame) 954 return; 955 956 m_frame->eventHandler().focusDocumentView(); 957 } 958 959 void LocalDOMWindow::blur() 960 { 961 } 962 963 void LocalDOMWindow::close(ExecutionContext* context) 964 { 965 if (!m_frame || !m_frame->isMainFrame()) 966 return; 967 968 Page* page = m_frame->page(); 969 if (!page) 970 return; 971 972 if (context) { 973 ASSERT(isMainThread()); 974 Document* activeDocument = toDocument(context); 975 if (!activeDocument) 976 return; 977 978 if (!activeDocument->canNavigate(*m_frame)) 979 return; 980 } 981 982 Settings* settings = m_frame->settings(); 983 bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows(); 984 985 if (!(page->openedByDOM() || page->backForward().backForwardListCount() <= 1 || allowScriptsToCloseWindows)) { 986 frameConsole()->addMessage(JSMessageSource, WarningMessageLevel, "Scripts may close only the windows that were opened by it."); 987 return; 988 } 989 990 if (!m_frame->loader().shouldClose()) 991 return; 992 993 page->chrome().closeWindowSoon(); 994 } 995 996 void LocalDOMWindow::print() 997 { 998 if (!m_frame) 999 return; 1000 1001 FrameHost* host = m_frame->host(); 1002 if (!host) 1003 return; 1004 1005 if (m_frame->loader().state() != FrameStateComplete) { 1006 m_shouldPrintWhenFinishedLoading = true; 1007 return; 1008 } 1009 m_shouldPrintWhenFinishedLoading = false; 1010 host->chrome().print(m_frame); 1011 } 1012 1013 void LocalDOMWindow::stop() 1014 { 1015 if (!m_frame) 1016 return; 1017 m_frame->loader().stopAllLoaders(); 1018 } 1019 1020 void LocalDOMWindow::alert(const String& message) 1021 { 1022 if (!m_frame) 1023 return; 1024 1025 m_frame->document()->updateRenderTreeIfNeeded(); 1026 1027 FrameHost* host = m_frame->host(); 1028 if (!host) 1029 return; 1030 1031 host->chrome().runJavaScriptAlert(m_frame, message); 1032 } 1033 1034 bool LocalDOMWindow::confirm(const String& message) 1035 { 1036 if (!m_frame) 1037 return false; 1038 1039 m_frame->document()->updateRenderTreeIfNeeded(); 1040 1041 FrameHost* host = m_frame->host(); 1042 if (!host) 1043 return false; 1044 1045 return host->chrome().runJavaScriptConfirm(m_frame, message); 1046 } 1047 1048 String LocalDOMWindow::prompt(const String& message, const String& defaultValue) 1049 { 1050 if (!m_frame) 1051 return String(); 1052 1053 m_frame->document()->updateRenderTreeIfNeeded(); 1054 1055 FrameHost* host = m_frame->host(); 1056 if (!host) 1057 return String(); 1058 1059 String returnValue; 1060 if (host->chrome().runJavaScriptPrompt(m_frame, message, defaultValue, returnValue)) 1061 return returnValue; 1062 1063 return String(); 1064 } 1065 1066 bool LocalDOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const 1067 { 1068 if (!isCurrentlyDisplayedInFrame()) 1069 return false; 1070 1071 // |m_frame| can be destructed during |Editor::findString()| via 1072 // |Document::updateLayou()|, e.g. event handler removes a frame. 1073 RefPtr<LocalFrame> protectFrame(m_frame); 1074 1075 // FIXME (13016): Support wholeWord, searchInFrames and showDialog 1076 return m_frame->editor().findString(string, !backwards, caseSensitive, wrap, false); 1077 } 1078 1079 bool LocalDOMWindow::offscreenBuffering() const 1080 { 1081 return true; 1082 } 1083 1084 int LocalDOMWindow::outerHeight() const 1085 { 1086 if (!m_frame) 1087 return 0; 1088 1089 FrameHost* host = m_frame->host(); 1090 if (!host) 1091 return 0; 1092 1093 if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) 1094 return lroundf(host->chrome().windowRect().height() * host->deviceScaleFactor()); 1095 return static_cast<int>(host->chrome().windowRect().height()); 1096 } 1097 1098 int LocalDOMWindow::outerWidth() const 1099 { 1100 if (!m_frame) 1101 return 0; 1102 1103 FrameHost* host = m_frame->host(); 1104 if (!host) 1105 return 0; 1106 1107 if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) 1108 return lroundf(host->chrome().windowRect().width() * host->deviceScaleFactor()); 1109 return static_cast<int>(host->chrome().windowRect().width()); 1110 } 1111 1112 int LocalDOMWindow::innerHeight() const 1113 { 1114 if (!m_frame) 1115 return 0; 1116 1117 FrameView* view = m_frame->view(); 1118 if (!view) 1119 return 0; 1120 1121 // FIXME: This is potentially too much work. We really only need to know the dimensions of the parent frame's renderer. 1122 if (Frame* parent = m_frame->tree().parent()) { 1123 if (parent && parent->isLocalFrame()) 1124 toLocalFrame(parent)->document()->updateLayoutIgnorePendingStylesheets(); 1125 } 1126 1127 return adjustForAbsoluteZoom(view->visibleContentRect(IncludeScrollbars).height(), m_frame->pageZoomFactor()); 1128 } 1129 1130 int LocalDOMWindow::innerWidth() const 1131 { 1132 if (!m_frame) 1133 return 0; 1134 1135 FrameView* view = m_frame->view(); 1136 if (!view) 1137 return 0; 1138 1139 // FIXME: This is potentially too much work. We really only need to know the dimensions of the parent frame's renderer. 1140 if (Frame* parent = m_frame->tree().parent()) { 1141 if (parent && parent->isLocalFrame()) 1142 toLocalFrame(parent)->document()->updateLayoutIgnorePendingStylesheets(); 1143 } 1144 1145 return adjustForAbsoluteZoom(view->visibleContentRect(IncludeScrollbars).width(), m_frame->pageZoomFactor()); 1146 } 1147 1148 int LocalDOMWindow::screenX() const 1149 { 1150 if (!m_frame) 1151 return 0; 1152 1153 FrameHost* host = m_frame->host(); 1154 if (!host) 1155 return 0; 1156 1157 if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) 1158 return lroundf(host->chrome().windowRect().x() * host->deviceScaleFactor()); 1159 return static_cast<int>(host->chrome().windowRect().x()); 1160 } 1161 1162 int LocalDOMWindow::screenY() const 1163 { 1164 if (!m_frame) 1165 return 0; 1166 1167 FrameHost* host = m_frame->host(); 1168 if (!host) 1169 return 0; 1170 1171 if (host->settings().reportScreenSizeInPhysicalPixelsQuirk()) 1172 return lroundf(host->chrome().windowRect().y() * host->deviceScaleFactor()); 1173 return static_cast<int>(host->chrome().windowRect().y()); 1174 } 1175 1176 int LocalDOMWindow::scrollX() const 1177 { 1178 if (!m_frame) 1179 return 0; 1180 1181 FrameView* view = m_frame->view(); 1182 if (!view) 1183 return 0; 1184 1185 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1186 1187 return adjustForAbsoluteZoom(view->scrollX(), m_frame->pageZoomFactor()); 1188 } 1189 1190 int LocalDOMWindow::scrollY() const 1191 { 1192 if (!m_frame) 1193 return 0; 1194 1195 FrameView* view = m_frame->view(); 1196 if (!view) 1197 return 0; 1198 1199 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1200 1201 return adjustForAbsoluteZoom(view->scrollY(), m_frame->pageZoomFactor()); 1202 } 1203 1204 bool LocalDOMWindow::closed() const 1205 { 1206 return !m_frame; 1207 } 1208 1209 unsigned LocalDOMWindow::length() const 1210 { 1211 if (!isCurrentlyDisplayedInFrame()) 1212 return 0; 1213 1214 return m_frame->tree().scopedChildCount(); 1215 } 1216 1217 const AtomicString& LocalDOMWindow::name() const 1218 { 1219 if (!isCurrentlyDisplayedInFrame()) 1220 return nullAtom; 1221 1222 return m_frame->tree().name(); 1223 } 1224 1225 void LocalDOMWindow::setName(const AtomicString& name) 1226 { 1227 if (!isCurrentlyDisplayedInFrame()) 1228 return; 1229 1230 m_frame->tree().setName(name); 1231 ASSERT(m_frame->loader().client()); 1232 m_frame->loader().client()->didChangeName(name); 1233 } 1234 1235 void LocalDOMWindow::setStatus(const String& string) 1236 { 1237 m_status = string; 1238 1239 if (!m_frame) 1240 return; 1241 1242 FrameHost* host = m_frame->host(); 1243 if (!host) 1244 return; 1245 1246 ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state. 1247 host->chrome().setStatusbarText(m_frame, m_status); 1248 } 1249 1250 void LocalDOMWindow::setDefaultStatus(const String& string) 1251 { 1252 m_defaultStatus = string; 1253 1254 if (!m_frame) 1255 return; 1256 1257 FrameHost* host = m_frame->host(); 1258 if (!host) 1259 return; 1260 1261 ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state. 1262 host->chrome().setStatusbarText(m_frame, m_defaultStatus); 1263 } 1264 1265 LocalDOMWindow* LocalDOMWindow::self() const 1266 { 1267 if (!m_frame) 1268 return 0; 1269 1270 return m_frame->domWindow(); 1271 } 1272 1273 LocalDOMWindow* LocalDOMWindow::opener() const 1274 { 1275 if (!m_frame) 1276 return 0; 1277 1278 LocalFrame* opener = m_frame->loader().opener(); 1279 if (!opener) 1280 return 0; 1281 1282 return opener->domWindow(); 1283 } 1284 1285 LocalDOMWindow* LocalDOMWindow::parent() const 1286 { 1287 if (!m_frame) 1288 return 0; 1289 1290 Frame* parent = m_frame->tree().parent(); 1291 if (parent) 1292 return parent->domWindow(); 1293 1294 return m_frame->domWindow(); 1295 } 1296 1297 LocalDOMWindow* LocalDOMWindow::top() const 1298 { 1299 if (!m_frame) 1300 return 0; 1301 1302 return m_frame->tree().top()->domWindow(); 1303 } 1304 1305 Document* LocalDOMWindow::document() const 1306 { 1307 return m_document.get(); 1308 } 1309 1310 StyleMedia& LocalDOMWindow::styleMedia() const 1311 { 1312 if (!m_media) 1313 m_media = StyleMedia::create(m_frame); 1314 return *m_media; 1315 } 1316 1317 PassRefPtrWillBeRawPtr<CSSStyleDeclaration> LocalDOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const 1318 { 1319 if (!elt) 1320 return nullptr; 1321 1322 return CSSComputedStyleDeclaration::create(elt, false, pseudoElt); 1323 } 1324 1325 PassRefPtrWillBeRawPtr<CSSRuleList> LocalDOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement) const 1326 { 1327 if (!element) 1328 return nullptr; 1329 1330 if (!isCurrentlyDisplayedInFrame()) 1331 return nullptr; 1332 1333 unsigned colonStart = pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0; 1334 CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(AtomicString(pseudoElement.substring(colonStart))); 1335 if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty()) 1336 return nullptr; 1337 1338 unsigned rulesToInclude = StyleResolver::AuthorCSSRules; 1339 PseudoId pseudoId = CSSSelector::pseudoId(pseudoType); 1340 return m_frame->document()->ensureStyleResolver().pseudoCSSRulesForElement(element, pseudoId, rulesToInclude); 1341 } 1342 1343 PassRefPtrWillBeRawPtr<DOMPoint> LocalDOMWindow::webkitConvertPointFromNodeToPage(Node* node, const DOMPoint* p) const 1344 { 1345 if (!node || !p) 1346 return nullptr; 1347 1348 if (!document()) 1349 return nullptr; 1350 1351 document()->updateLayoutIgnorePendingStylesheets(); 1352 1353 FloatPoint pagePoint(p->x(), p->y()); 1354 pagePoint = node->convertToPage(pagePoint); 1355 return DOMPoint::create(pagePoint.x(), pagePoint.y()); 1356 } 1357 1358 PassRefPtrWillBeRawPtr<DOMPoint> LocalDOMWindow::webkitConvertPointFromPageToNode(Node* node, const DOMPoint* p) const 1359 { 1360 if (!node || !p) 1361 return nullptr; 1362 1363 if (!document()) 1364 return nullptr; 1365 1366 document()->updateLayoutIgnorePendingStylesheets(); 1367 1368 FloatPoint nodePoint(p->x(), p->y()); 1369 nodePoint = node->convertFromPage(nodePoint); 1370 return DOMPoint::create(nodePoint.x(), nodePoint.y()); 1371 } 1372 1373 double LocalDOMWindow::devicePixelRatio() const 1374 { 1375 if (!m_frame) 1376 return 0.0; 1377 1378 return m_frame->devicePixelRatio(); 1379 } 1380 1381 static bool scrollBehaviorFromScrollOptions(const Dictionary& scrollOptions, ScrollBehavior& scrollBehavior, ExceptionState& exceptionState) 1382 { 1383 String scrollBehaviorString; 1384 if (!scrollOptions.get("behavior", scrollBehaviorString)) { 1385 scrollBehavior = ScrollBehaviorAuto; 1386 return true; 1387 } 1388 1389 if (ScrollableArea::scrollBehaviorFromString(scrollBehaviorString, scrollBehavior)) 1390 return true; 1391 1392 exceptionState.throwTypeError("The ScrollBehavior provided is invalid."); 1393 return false; 1394 } 1395 1396 void LocalDOMWindow::scrollBy(int x, int y) const 1397 { 1398 if (!isCurrentlyDisplayedInFrame()) 1399 return; 1400 1401 document()->updateLayoutIgnorePendingStylesheets(); 1402 1403 FrameView* view = m_frame->view(); 1404 if (!view) 1405 return; 1406 1407 IntSize scaledOffset(x * m_frame->pageZoomFactor(), y * m_frame->pageZoomFactor()); 1408 // FIXME: Use scrollBehavior to decide whether to scroll smoothly or instantly. 1409 view->scrollBy(scaledOffset); 1410 } 1411 1412 void LocalDOMWindow::scrollBy(int x, int y, const Dictionary& scrollOptions, ExceptionState &exceptionState) const 1413 { 1414 ScrollBehavior scrollBehavior = ScrollBehaviorAuto; 1415 if (!scrollBehaviorFromScrollOptions(scrollOptions, scrollBehavior, exceptionState)) 1416 return; 1417 scrollBy(x, y); 1418 } 1419 1420 void LocalDOMWindow::scrollTo(int x, int y) const 1421 { 1422 if (!isCurrentlyDisplayedInFrame()) 1423 return; 1424 1425 document()->updateLayoutIgnorePendingStylesheets(); 1426 1427 RefPtr<FrameView> view = m_frame->view(); 1428 if (!view) 1429 return; 1430 1431 IntPoint layoutPos(x * m_frame->pageZoomFactor(), y * m_frame->pageZoomFactor()); 1432 // FIXME: Use scrollBehavior to decide whether to scroll smoothly or instantly. 1433 view->setScrollPosition(layoutPos); 1434 } 1435 1436 void LocalDOMWindow::scrollTo(int x, int y, const Dictionary& scrollOptions, ExceptionState& exceptionState) const 1437 { 1438 ScrollBehavior scrollBehavior = ScrollBehaviorAuto; 1439 if (!scrollBehaviorFromScrollOptions(scrollOptions, scrollBehavior, exceptionState)) 1440 return; 1441 scrollTo(x, y); 1442 } 1443 1444 void LocalDOMWindow::moveBy(float x, float y) const 1445 { 1446 if (!m_frame || !m_frame->isMainFrame()) 1447 return; 1448 1449 FrameHost* host = m_frame->host(); 1450 if (!host) 1451 return; 1452 1453 FloatRect windowRect = host->chrome().windowRect(); 1454 windowRect.move(x, y); 1455 // Security check (the spec talks about UniversalBrowserWrite to disable this check...) 1456 host->chrome().setWindowRect(adjustWindowRect(*m_frame, windowRect)); 1457 } 1458 1459 void LocalDOMWindow::moveTo(float x, float y) const 1460 { 1461 if (!m_frame || !m_frame->isMainFrame()) 1462 return; 1463 1464 FrameHost* host = m_frame->host(); 1465 if (!host) 1466 return; 1467 1468 FloatRect windowRect = host->chrome().windowRect(); 1469 windowRect.setLocation(FloatPoint(x, y)); 1470 // Security check (the spec talks about UniversalBrowserWrite to disable this check...) 1471 host->chrome().setWindowRect(adjustWindowRect(*m_frame, windowRect)); 1472 } 1473 1474 void LocalDOMWindow::resizeBy(float x, float y) const 1475 { 1476 if (!m_frame || !m_frame->isMainFrame()) 1477 return; 1478 1479 FrameHost* host = m_frame->host(); 1480 if (!host) 1481 return; 1482 1483 FloatRect fr = host->chrome().windowRect(); 1484 FloatSize dest = fr.size() + FloatSize(x, y); 1485 FloatRect update(fr.location(), dest); 1486 host->chrome().setWindowRect(adjustWindowRect(*m_frame, update)); 1487 } 1488 1489 void LocalDOMWindow::resizeTo(float width, float height) const 1490 { 1491 if (!m_frame || !m_frame->isMainFrame()) 1492 return; 1493 1494 FrameHost* host = m_frame->host(); 1495 if (!host) 1496 return; 1497 1498 FloatRect fr = host->chrome().windowRect(); 1499 FloatSize dest = FloatSize(width, height); 1500 FloatRect update(fr.location(), dest); 1501 host->chrome().setWindowRect(adjustWindowRect(*m_frame, update)); 1502 } 1503 1504 int LocalDOMWindow::requestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback) 1505 { 1506 callback->m_useLegacyTimeBase = false; 1507 if (Document* d = document()) 1508 return d->requestAnimationFrame(callback); 1509 return 0; 1510 } 1511 1512 int LocalDOMWindow::webkitRequestAnimationFrame(PassOwnPtr<RequestAnimationFrameCallback> callback) 1513 { 1514 callback->m_useLegacyTimeBase = true; 1515 if (Document* d = document()) 1516 return d->requestAnimationFrame(callback); 1517 return 0; 1518 } 1519 1520 void LocalDOMWindow::cancelAnimationFrame(int id) 1521 { 1522 if (Document* d = document()) 1523 d->cancelAnimationFrame(id); 1524 } 1525 1526 DOMWindowCSS& LocalDOMWindow::css() const 1527 { 1528 if (!m_css) 1529 m_css = DOMWindowCSS::create(); 1530 return *m_css; 1531 } 1532 1533 static void didAddStorageEventListener(LocalDOMWindow* window) 1534 { 1535 // Creating these WebCore::Storage objects informs the system that we'd like to receive 1536 // notifications about storage events that might be triggered in other processes. Rather 1537 // than subscribe to these notifications explicitly, we subscribe to them implicitly to 1538 // simplify the work done by the system. 1539 window->localStorage(IGNORE_EXCEPTION); 1540 window->sessionStorage(IGNORE_EXCEPTION); 1541 } 1542 1543 bool LocalDOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 1544 { 1545 if (!EventTarget::addEventListener(eventType, listener, useCapture)) 1546 return false; 1547 1548 if (m_frame && m_frame->host()) 1549 m_frame->host()->eventHandlerRegistry().didAddEventHandler(*this, eventType); 1550 1551 if (Document* document = this->document()) { 1552 document->addListenerTypeIfNeeded(eventType); 1553 if (isTouchEventType(eventType)) 1554 document->didAddTouchEventHandler(document); 1555 else if (eventType == EventTypeNames::storage) 1556 didAddStorageEventListener(this); 1557 } 1558 1559 lifecycleNotifier().notifyAddEventListener(this, eventType); 1560 1561 if (eventType == EventTypeNames::unload) { 1562 UseCounter::count(document(), UseCounter::DocumentUnloadRegistered); 1563 addUnloadEventListener(this); 1564 } else if (eventType == EventTypeNames::beforeunload) { 1565 UseCounter::count(document(), UseCounter::DocumentBeforeUnloadRegistered); 1566 if (allowsBeforeUnloadListeners(this)) { 1567 // This is confusingly named. It doesn't actually add the listener. It just increments a count 1568 // so that we know we have listeners registered for the purposes of determining if we can 1569 // fast terminate the renderer process. 1570 addBeforeUnloadEventListener(this); 1571 } else { 1572 // Subframes return false from allowsBeforeUnloadListeners. 1573 UseCounter::count(document(), UseCounter::SubFrameBeforeUnloadRegistered); 1574 } 1575 } 1576 1577 return true; 1578 } 1579 1580 bool LocalDOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 1581 { 1582 if (!EventTarget::removeEventListener(eventType, listener, useCapture)) 1583 return false; 1584 1585 if (m_frame && m_frame->host()) 1586 m_frame->host()->eventHandlerRegistry().didRemoveEventHandler(*this, eventType); 1587 1588 if (Document* document = this->document()) { 1589 if (isTouchEventType(eventType)) 1590 document->didRemoveTouchEventHandler(document); 1591 } 1592 1593 lifecycleNotifier().notifyRemoveEventListener(this, eventType); 1594 1595 if (eventType == EventTypeNames::unload) { 1596 removeUnloadEventListener(this); 1597 } else if (eventType == EventTypeNames::beforeunload && allowsBeforeUnloadListeners(this)) { 1598 removeBeforeUnloadEventListener(this); 1599 } 1600 1601 return true; 1602 } 1603 1604 void LocalDOMWindow::dispatchLoadEvent() 1605 { 1606 RefPtrWillBeRawPtr<Event> loadEvent(Event::create(EventTypeNames::load)); 1607 if (m_frame && m_frame->loader().documentLoader() && !m_frame->loader().documentLoader()->timing()->loadEventStart()) { 1608 // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching 1609 // the event, so protect it to prevent writing the end time into freed memory. 1610 RefPtr<DocumentLoader> documentLoader = m_frame->loader().documentLoader(); 1611 DocumentLoadTiming* timing = documentLoader->timing(); 1612 timing->markLoadEventStart(); 1613 dispatchEvent(loadEvent, document()); 1614 timing->markLoadEventEnd(); 1615 } else 1616 dispatchEvent(loadEvent, document()); 1617 1618 // For load events, send a separate load event to the enclosing frame only. 1619 // This is a DOM extension and is independent of bubbling/capturing rules of 1620 // the DOM. 1621 FrameOwner* owner = m_frame ? m_frame->owner() : 0; 1622 if (owner) 1623 owner->dispatchLoad(); 1624 1625 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "MarkLoad", "data", InspectorMarkLoadEvent::data(frame())); 1626 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 1627 InspectorInstrumentation::loadEventFired(frame()); 1628 } 1629 1630 bool LocalDOMWindow::dispatchEvent(PassRefPtrWillBeRawPtr<Event> prpEvent, PassRefPtrWillBeRawPtr<EventTarget> prpTarget) 1631 { 1632 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 1633 1634 RefPtrWillBeRawPtr<EventTarget> protect(this); 1635 RefPtrWillBeRawPtr<Event> event = prpEvent; 1636 1637 event->setTarget(prpTarget ? prpTarget : this); 1638 event->setCurrentTarget(this); 1639 event->setEventPhase(Event::AT_TARGET); 1640 1641 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EventDispatch", "type", event->type().ascii()); 1642 // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. 1643 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this); 1644 1645 bool result = fireEventListeners(event.get()); 1646 1647 InspectorInstrumentation::didDispatchEventOnWindow(cookie); 1648 1649 return result; 1650 } 1651 1652 void LocalDOMWindow::removeAllEventListenersInternal(BroadcastListenerRemoval mode) 1653 { 1654 EventTarget::removeAllEventListeners(); 1655 1656 lifecycleNotifier().notifyRemoveAllEventListeners(this); 1657 1658 if (mode == DoBroadcastListenerRemoval) { 1659 if (m_frame && m_frame->host()) 1660 m_frame->host()->eventHandlerRegistry().didRemoveAllEventHandlers(*this); 1661 1662 if (Document* document = this->document()) 1663 document->didClearTouchEventHandlers(document); 1664 } 1665 1666 removeAllUnloadEventListeners(this); 1667 removeAllBeforeUnloadEventListeners(this); 1668 } 1669 1670 void LocalDOMWindow::removeAllEventListeners() 1671 { 1672 removeAllEventListenersInternal(DoBroadcastListenerRemoval); 1673 } 1674 1675 void LocalDOMWindow::finishedLoading() 1676 { 1677 if (m_shouldPrintWhenFinishedLoading) { 1678 m_shouldPrintWhenFinishedLoading = false; 1679 print(); 1680 } 1681 } 1682 1683 void LocalDOMWindow::setLocation(const String& urlString, LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, SetLocationLocking locking) 1684 { 1685 if (!isCurrentlyDisplayedInFrame()) 1686 return; 1687 1688 Document* activeDocument = callingWindow->document(); 1689 if (!activeDocument) 1690 return; 1691 1692 ASSERT(m_frame); 1693 if (!activeDocument->canNavigate(*m_frame)) 1694 return; 1695 1696 LocalFrame* firstFrame = enteredWindow->frame(); 1697 if (!firstFrame) 1698 return; 1699 1700 KURL completedURL = firstFrame->document()->completeURL(urlString); 1701 if (completedURL.isNull()) 1702 return; 1703 1704 if (isInsecureScriptAccess(*callingWindow, completedURL)) 1705 return; 1706 1707 // We want a new history item if we are processing a user gesture. 1708 m_frame->navigationScheduler().scheduleLocationChange(activeDocument, 1709 // FIXME: What if activeDocument()->frame() is 0? 1710 completedURL, Referrer(activeDocument->outgoingReferrer(), activeDocument->referrerPolicy()), 1711 locking != LockHistoryBasedOnGestureState); 1712 } 1713 1714 void LocalDOMWindow::printErrorMessage(const String& message) 1715 { 1716 if (message.isEmpty()) 1717 return; 1718 1719 frameConsole()->addMessage(JSMessageSource, ErrorMessageLevel, message); 1720 } 1721 1722 // FIXME: Once we're throwing exceptions for cross-origin access violations, we will always sanitize the target 1723 // frame details, so we can safely combine 'crossDomainAccessErrorMessage' with this method after considering 1724 // exactly which details may be exposed to JavaScript. 1725 // 1726 // http://crbug.com/17325 1727 String LocalDOMWindow::sanitizedCrossDomainAccessErrorMessage(LocalDOMWindow* callingWindow) 1728 { 1729 if (!callingWindow || !callingWindow->document()) 1730 return String(); 1731 1732 const KURL& callingWindowURL = callingWindow->document()->url(); 1733 if (callingWindowURL.isNull()) 1734 return String(); 1735 1736 ASSERT(!callingWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())); 1737 1738 SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); 1739 String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a cross-origin frame."; 1740 1741 // FIXME: Evaluate which details from 'crossDomainAccessErrorMessage' may safely be reported to JavaScript. 1742 1743 return message; 1744 } 1745 1746 String LocalDOMWindow::crossDomainAccessErrorMessage(LocalDOMWindow* callingWindow) 1747 { 1748 if (!callingWindow || !callingWindow->document()) 1749 return String(); 1750 1751 const KURL& callingWindowURL = callingWindow->document()->url(); 1752 if (callingWindowURL.isNull()) 1753 return String(); 1754 1755 ASSERT(!callingWindow->document()->securityOrigin()->canAccess(document()->securityOrigin())); 1756 1757 // FIXME: This message, and other console messages, have extra newlines. Should remove them. 1758 SecurityOrigin* activeOrigin = callingWindow->document()->securityOrigin(); 1759 SecurityOrigin* targetOrigin = document()->securityOrigin(); 1760 String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a frame with origin \"" + targetOrigin->toString() + "\". "; 1761 1762 // Sandbox errors: Use the origin of the frames' location, rather than their actual origin (since we know that at least one will be "null"). 1763 KURL activeURL = callingWindow->document()->url(); 1764 KURL targetURL = document()->url(); 1765 if (document()->isSandboxed(SandboxOrigin) || callingWindow->document()->isSandboxed(SandboxOrigin)) { 1766 message = "Blocked a frame at \"" + SecurityOrigin::create(activeURL)->toString() + "\" from accessing a frame at \"" + SecurityOrigin::create(targetURL)->toString() + "\". "; 1767 if (document()->isSandboxed(SandboxOrigin) && callingWindow->document()->isSandboxed(SandboxOrigin)) 1768 return "Sandbox access violation: " + message + " Both frames are sandboxed and lack the \"allow-same-origin\" flag."; 1769 if (document()->isSandboxed(SandboxOrigin)) 1770 return "Sandbox access violation: " + message + " The frame being accessed is sandboxed and lacks the \"allow-same-origin\" flag."; 1771 return "Sandbox access violation: " + message + " The frame requesting access is sandboxed and lacks the \"allow-same-origin\" flag."; 1772 } 1773 1774 // Protocol errors: Use the URL's protocol rather than the origin's protocol so that we get a useful message for non-heirarchal URLs like 'data:'. 1775 if (targetOrigin->protocol() != activeOrigin->protocol()) 1776 return message + " The frame requesting access has a protocol of \"" + activeURL.protocol() + "\", the frame being accessed has a protocol of \"" + targetURL.protocol() + "\". Protocols must match.\n"; 1777 1778 // 'document.domain' errors. 1779 if (targetOrigin->domainWasSetInDOM() && activeOrigin->domainWasSetInDOM()) 1780 return message + "The frame requesting access set \"document.domain\" to \"" + activeOrigin->domain() + "\", the frame being accessed set it to \"" + targetOrigin->domain() + "\". Both must set \"document.domain\" to the same value to allow access."; 1781 if (activeOrigin->domainWasSetInDOM()) 1782 return message + "The frame requesting access set \"document.domain\" to \"" + activeOrigin->domain() + "\", but the frame being accessed did not. Both must set \"document.domain\" to the same value to allow access."; 1783 if (targetOrigin->domainWasSetInDOM()) 1784 return message + "The frame being accessed set \"document.domain\" to \"" + targetOrigin->domain() + "\", but the frame requesting access did not. Both must set \"document.domain\" to the same value to allow access."; 1785 1786 // Default. 1787 return message + "Protocols, domains, and ports must match."; 1788 } 1789 1790 bool LocalDOMWindow::isInsecureScriptAccess(LocalDOMWindow& callingWindow, const String& urlString) 1791 { 1792 if (!protocolIsJavaScript(urlString)) 1793 return false; 1794 1795 // If this LocalDOMWindow isn't currently active in the LocalFrame, then there's no 1796 // way we should allow the access. 1797 // FIXME: Remove this check if we're able to disconnect LocalDOMWindow from 1798 // LocalFrame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054 1799 if (isCurrentlyDisplayedInFrame()) { 1800 // FIXME: Is there some way to eliminate the need for a separate "callingWindow == this" check? 1801 if (&callingWindow == this) 1802 return false; 1803 1804 // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script". 1805 // Can we name the SecurityOrigin function better to make this more clear? 1806 if (callingWindow.document()->securityOrigin()->canAccess(document()->securityOrigin())) 1807 return false; 1808 } 1809 1810 printErrorMessage(crossDomainAccessErrorMessage(&callingWindow)); 1811 return true; 1812 } 1813 1814 PassRefPtrWillBeRawPtr<LocalDOMWindow> LocalDOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString, 1815 LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow) 1816 { 1817 if (!isCurrentlyDisplayedInFrame()) 1818 return nullptr; 1819 Document* activeDocument = callingWindow->document(); 1820 if (!activeDocument) 1821 return nullptr; 1822 LocalFrame* firstFrame = enteredWindow->frame(); 1823 if (!firstFrame) 1824 return nullptr; 1825 1826 if (!enteredWindow->allowPopUp()) { 1827 // Because FrameTree::find() returns true for empty strings, we must check for empty frame names. 1828 // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker. 1829 if (frameName.isEmpty() || !m_frame->tree().find(frameName)) 1830 return nullptr; 1831 } 1832 1833 // Get the target frame for the special cases of _top and _parent. 1834 // In those cases, we schedule a location change right now and return early. 1835 Frame* targetFrame = 0; 1836 if (frameName == "_top") 1837 targetFrame = m_frame->tree().top(); 1838 else if (frameName == "_parent") { 1839 if (Frame* parent = m_frame->tree().parent()) 1840 targetFrame = parent; 1841 else 1842 targetFrame = m_frame; 1843 } 1844 // FIXME: Navigating RemoteFrames is not yet supported. 1845 if (targetFrame && targetFrame->isLocalFrame()) { 1846 if (!activeDocument->canNavigate(*targetFrame)) 1847 return nullptr; 1848 1849 KURL completedURL = firstFrame->document()->completeURL(urlString); 1850 1851 if (targetFrame->domWindow()->isInsecureScriptAccess(*callingWindow, completedURL)) 1852 return targetFrame->domWindow(); 1853 1854 if (urlString.isEmpty()) 1855 return targetFrame->domWindow(); 1856 1857 // For whatever reason, Firefox uses the first window rather than the active window to 1858 // determine the outgoing referrer. We replicate that behavior here. 1859 toLocalFrame(targetFrame)->navigationScheduler().scheduleLocationChange( 1860 activeDocument, 1861 completedURL, 1862 Referrer(firstFrame->document()->outgoingReferrer(), firstFrame->document()->referrerPolicy()), 1863 false); 1864 return targetFrame->domWindow(); 1865 } 1866 1867 WindowFeatures windowFeatures(windowFeaturesString); 1868 LocalFrame* result = createWindow(urlString, frameName, windowFeatures, *callingWindow, *firstFrame, *m_frame); 1869 return result ? result->domWindow() : 0; 1870 } 1871 1872 void LocalDOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString, 1873 LocalDOMWindow* callingWindow, LocalDOMWindow* enteredWindow, PrepareDialogFunction function, void* functionContext) 1874 { 1875 if (!isCurrentlyDisplayedInFrame()) 1876 return; 1877 LocalFrame* activeFrame = callingWindow->frame(); 1878 if (!activeFrame) 1879 return; 1880 LocalFrame* firstFrame = enteredWindow->frame(); 1881 if (!firstFrame) 1882 return; 1883 1884 if (!canShowModalDialogNow(m_frame) || !enteredWindow->allowPopUp()) 1885 return; 1886 1887 UseCounter::countDeprecation(this, UseCounter::ShowModalDialog); 1888 1889 WindowFeatures windowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())); 1890 LocalFrame* dialogFrame = createWindow(urlString, emptyAtom, windowFeatures, 1891 *callingWindow, *firstFrame, *m_frame, function, functionContext); 1892 if (!dialogFrame) 1893 return; 1894 UserGestureIndicatorDisabler disabler; 1895 dialogFrame->host()->chrome().runModal(); 1896 } 1897 1898 LocalDOMWindow* LocalDOMWindow::anonymousIndexedGetter(uint32_t index) 1899 { 1900 LocalFrame* frame = this->frame(); 1901 if (!frame) 1902 return 0; 1903 1904 Frame* child = frame->tree().scopedChild(index); 1905 if (child) 1906 return child->domWindow(); 1907 1908 return 0; 1909 } 1910 1911 DOMWindowLifecycleNotifier& LocalDOMWindow::lifecycleNotifier() 1912 { 1913 return static_cast<DOMWindowLifecycleNotifier&>(LifecycleContext<LocalDOMWindow>::lifecycleNotifier()); 1914 } 1915 1916 PassOwnPtr<LifecycleNotifier<LocalDOMWindow> > LocalDOMWindow::createLifecycleNotifier() 1917 { 1918 return DOMWindowLifecycleNotifier::create(this); 1919 } 1920 1921 void LocalDOMWindow::trace(Visitor* visitor) 1922 { 1923 visitor->trace(m_document); 1924 visitor->trace(m_screen); 1925 visitor->trace(m_history); 1926 visitor->trace(m_locationbar); 1927 visitor->trace(m_menubar); 1928 visitor->trace(m_personalbar); 1929 visitor->trace(m_scrollbars); 1930 visitor->trace(m_statusbar); 1931 visitor->trace(m_toolbar); 1932 visitor->trace(m_console); 1933 visitor->trace(m_navigator); 1934 visitor->trace(m_location); 1935 visitor->trace(m_media); 1936 visitor->trace(m_sessionStorage); 1937 visitor->trace(m_localStorage); 1938 visitor->trace(m_applicationCache); 1939 visitor->trace(m_performance); 1940 visitor->trace(m_css); 1941 visitor->trace(m_eventQueue); 1942 WillBeHeapSupplementable<LocalDOMWindow>::trace(visitor); 1943 EventTargetWithInlineData::trace(visitor); 1944 } 1945 1946 } // namespace WebCore 1947