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