Make some things that return never-null pointers return references instead.
[WebKit-https.git] / Source / WebCore / page / DOMWindow.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2010, 2013 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 "DOMWindow.h"
29
30 #include "BackForwardController.h"
31 #include "BarProp.h"
32 #include "BeforeUnloadEvent.h"
33 #include "CSSComputedStyleDeclaration.h"
34 #include "CSSRule.h"
35 #include "CSSRuleList.h"
36 #include "Chrome.h"
37 #include "ChromeClient.h"
38 #include "Console.h"
39 #include "Crypto.h"
40 #include "DOMApplicationCache.h"
41 #include "DOMSelection.h"
42 #include "DOMSettableTokenList.h"
43 #include "DOMStringList.h"
44 #include "DOMTimer.h"
45 #include "DOMTokenList.h"
46 #include "DOMURL.h"
47 #include "DOMWindowCSS.h"
48 #include "DOMWindowExtension.h"
49 #include "DOMWindowNotifications.h"
50 #include "DeviceMotionController.h"
51 #include "DeviceOrientationController.h"
52 #include "Document.h"
53 #include "DocumentLoader.h"
54 #include "Editor.h"
55 #include "Element.h"
56 #include "EventException.h"
57 #include "EventHandler.h"
58 #include "EventListener.h"
59 #include "EventNames.h"
60 #include "ExceptionCode.h"
61 #include "ExceptionCodePlaceholder.h"
62 #include "FloatRect.h"
63 #include "FocusController.h"
64 #include "Frame.h"
65 #include "FrameLoadRequest.h"
66 #include "FrameLoader.h"
67 #include "FrameLoaderClient.h"
68 #include "FrameTree.h"
69 #include "FrameView.h"
70 #include "HTMLFrameOwnerElement.h"
71 #include "History.h"
72 #include "InspectorInstrumentation.h"
73 #include "KURL.h"
74 #include "Location.h"
75 #include "MediaQueryList.h"
76 #include "MediaQueryMatcher.h"
77 #include "MessageEvent.h"
78 #include "Navigator.h"
79 #include "Page.h"
80 #include "PageConsole.h"
81 #include "PageGroup.h"
82 #include "PageTransitionEvent.h"
83 #include "Performance.h"
84 #include "PlatformScreen.h"
85 #include "RuntimeEnabledFeatures.h"
86 #include "ScheduledAction.h"
87 #include "Screen.h"
88 #include "ScriptCallStack.h"
89 #include "ScriptCallStackFactory.h"
90 #include "ScriptController.h"
91 #include "SecurityOrigin.h"
92 #include "SecurityPolicy.h"
93 #include "SerializedScriptValue.h"
94 #include "Settings.h"
95 #include "Storage.h"
96 #include "StorageArea.h"
97 #include "StorageNamespace.h"
98 #include "StyleMedia.h"
99 #include "StyleResolver.h"
100 #include "SuddenTermination.h"
101 #include "WebKitPoint.h"
102 #include "WindowFeatures.h"
103 #include "WindowFocusAllowedIndicator.h"
104 #include <algorithm>
105 #include <wtf/CurrentTime.h>
106 #include <wtf/MainThread.h>
107 #include <wtf/MathExtras.h>
108 #include <wtf/text/Base64.h>
109 #include <wtf/text/WTFString.h>
110
111 #if ENABLE(PROXIMITY_EVENTS)
112 #include "DeviceProximityController.h"
113 #endif
114
115 #if ENABLE(REQUEST_ANIMATION_FRAME)
116 #include "RequestAnimationFrameCallback.h"
117 #endif
118
119 using std::min;
120 using std::max;
121
122 namespace WebCore {
123
124 class PostMessageTimer : public TimerBase {
125 public:
126     PostMessageTimer(DOMWindow* window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtr<ScriptCallStack> stackTrace)
127         : m_window(window)
128         , m_message(message)
129         , m_origin(sourceOrigin)
130         , m_source(source)
131         , m_channels(channels)
132         , m_targetOrigin(targetOrigin)
133         , m_stackTrace(stackTrace)
134     {
135     }
136
137     PassRefPtr<MessageEvent> event(ScriptExecutionContext* context)
138     {
139         OwnPtr<MessagePortArray> messagePorts = MessagePort::entanglePorts(*context, m_channels.release());
140         return MessageEvent::create(messagePorts.release(), m_message, m_origin, "", m_source);
141     }
142     SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
143     ScriptCallStack* stackTrace() const { return m_stackTrace.get(); }
144
145 private:
146     virtual void fired()
147     {
148         m_window->postMessageTimerFired(adoptPtr(this));
149         // This object is deleted now.
150     }
151
152     RefPtr<DOMWindow> m_window;
153     RefPtr<SerializedScriptValue> m_message;
154     String m_origin;
155     RefPtr<DOMWindow> m_source;
156     OwnPtr<MessagePortChannelArray> m_channels;
157     RefPtr<SecurityOrigin> m_targetOrigin;
158     RefPtr<ScriptCallStack> m_stackTrace;
159 };
160
161 typedef HashCountedSet<DOMWindow*> DOMWindowSet;
162
163 static DOMWindowSet& windowsWithUnloadEventListeners()
164 {
165     DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ());
166     return windowsWithUnloadEventListeners;
167 }
168
169 static DOMWindowSet& windowsWithBeforeUnloadEventListeners()
170 {
171     DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ());
172     return windowsWithBeforeUnloadEventListeners;
173 }
174
175 static void addUnloadEventListener(DOMWindow* domWindow)
176 {
177     DOMWindowSet& set = windowsWithUnloadEventListeners();
178     if (set.add(domWindow).isNewEntry)
179         domWindow->disableSuddenTermination();
180 }
181
182 static void removeUnloadEventListener(DOMWindow* domWindow)
183 {
184     DOMWindowSet& set = windowsWithUnloadEventListeners();
185     DOMWindowSet::iterator it = set.find(domWindow);
186     if (set.remove(it))
187         domWindow->enableSuddenTermination();
188 }
189
190 static void removeAllUnloadEventListeners(DOMWindow* domWindow)
191 {
192     DOMWindowSet& set = windowsWithUnloadEventListeners();
193     DOMWindowSet::iterator it = set.find(domWindow);
194     if (it == set.end())
195         return;
196     set.removeAll(it);
197     domWindow->enableSuddenTermination();
198 }
199
200 static void addBeforeUnloadEventListener(DOMWindow* domWindow)
201 {
202     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
203     if (set.add(domWindow).isNewEntry)
204         domWindow->disableSuddenTermination();
205 }
206
207 static void removeBeforeUnloadEventListener(DOMWindow* domWindow)
208 {
209     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
210     DOMWindowSet::iterator it = set.find(domWindow);
211     if (set.remove(it))
212         domWindow->enableSuddenTermination();
213 }
214
215 static void removeAllBeforeUnloadEventListeners(DOMWindow* domWindow)
216 {
217     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
218     DOMWindowSet::iterator it = set.find(domWindow);
219     if (it == set.end())
220         return;
221     set.removeAll(it);
222     domWindow->enableSuddenTermination();
223 }
224
225 static bool allowsBeforeUnloadListeners(DOMWindow* window)
226 {
227     ASSERT_ARG(window, window);
228     Frame* frame = window->frame();
229     if (!frame)
230         return false;
231     Page* page = frame->page();
232     if (!page)
233         return false;
234     return frame == page->mainFrame();
235 }
236
237 bool DOMWindow::dispatchAllPendingBeforeUnloadEvents()
238 {
239     DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
240     if (set.isEmpty())
241         return true;
242
243     static bool alreadyDispatched = false;
244     ASSERT(!alreadyDispatched);
245     if (alreadyDispatched)
246         return true;
247
248     Vector<RefPtr<DOMWindow> > windows;
249     DOMWindowSet::iterator end = set.end();
250     for (DOMWindowSet::iterator it = set.begin(); it != end; ++it)
251         windows.append(it->key);
252
253     size_t size = windows.size();
254     for (size_t i = 0; i < size; ++i) {
255         DOMWindow* window = windows[i].get();
256         if (!set.contains(window))
257             continue;
258
259         Frame* frame = window->frame();
260         if (!frame)
261             continue;
262
263         if (!frame->loader()->shouldClose())
264             return false;
265
266         window->enableSuddenTermination();
267     }
268
269     alreadyDispatched = true;
270     return true;
271 }
272
273 unsigned DOMWindow::pendingUnloadEventListeners() const
274 {
275     return windowsWithUnloadEventListeners().count(const_cast<DOMWindow*>(this));
276 }
277
278 void DOMWindow::dispatchAllPendingUnloadEvents()
279 {
280     DOMWindowSet& set = windowsWithUnloadEventListeners();
281     if (set.isEmpty())
282         return;
283
284     static bool alreadyDispatched = false;
285     ASSERT(!alreadyDispatched);
286     if (alreadyDispatched)
287         return;
288
289     Vector<RefPtr<DOMWindow> > windows;
290     DOMWindowSet::iterator end = set.end();
291     for (DOMWindowSet::iterator it = set.begin(); it != end; ++it)
292         windows.append(it->key);
293
294     size_t size = windows.size();
295     for (size_t i = 0; i < size; ++i) {
296         DOMWindow* window = windows[i].get();
297         if (!set.contains(window))
298             continue;
299
300         window->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), window->document());
301         window->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), window->document());
302
303         window->enableSuddenTermination();
304     }
305
306     alreadyDispatched = true;
307 }
308
309 // This function:
310 // 1) Validates the pending changes are not changing any value to NaN; in that case keep original value.
311 // 2) Constrains the window rect to the minimum window size and no bigger than the float rect's dimensions.
312 // 3) Constrains the window rect to within the top and left boundaries of the available screen rect.
313 // 4) Constrains the window rect to within the bottom and right boundaries of the available screen rect.
314 // 5) Translate the window rect coordinates to be within the coordinate space of the screen.
315 FloatRect DOMWindow::adjustWindowRect(Page* page, const FloatRect& pendingChanges)
316 {
317     ASSERT(page);
318
319     FloatRect screen = screenAvailableRect(page->mainFrame()->view());
320     FloatRect window = page->chrome().windowRect();
321
322     // Make sure we're in a valid state before adjusting dimensions.
323     ASSERT(std::isfinite(screen.x()));
324     ASSERT(std::isfinite(screen.y()));
325     ASSERT(std::isfinite(screen.width()));
326     ASSERT(std::isfinite(screen.height()));
327     ASSERT(std::isfinite(window.x()));
328     ASSERT(std::isfinite(window.y()));
329     ASSERT(std::isfinite(window.width()));
330     ASSERT(std::isfinite(window.height()));
331
332     // Update window values if new requested values are not NaN.
333     if (!std::isnan(pendingChanges.x()))
334         window.setX(pendingChanges.x());
335     if (!std::isnan(pendingChanges.y()))
336         window.setY(pendingChanges.y());
337     if (!std::isnan(pendingChanges.width()))
338         window.setWidth(pendingChanges.width());
339     if (!std::isnan(pendingChanges.height()))
340         window.setHeight(pendingChanges.height());
341
342     FloatSize minimumSize = page->chrome().client()->minimumWindowSize();
343     window.setWidth(min(max(minimumSize.width(), window.width()), screen.width()));
344     window.setHeight(min(max(minimumSize.height(), window.height()), screen.height()));
345
346     // Constrain the window position within the valid screen area.
347     window.setX(max(screen.x(), min(window.x(), screen.maxX() - window.width())));
348     window.setY(max(screen.y(), min(window.y(), screen.maxY() - window.height())));
349
350     return window;
351 }
352
353 bool DOMWindow::allowPopUp(Frame* firstFrame)
354 {
355     ASSERT(firstFrame);
356
357     if (ScriptController::processingUserGesture())
358         return true;
359
360     Settings* settings = firstFrame->settings();
361     return settings && settings->javaScriptCanOpenWindowsAutomatically();
362 }
363
364 bool DOMWindow::allowPopUp()
365 {
366     return m_frame && allowPopUp(m_frame);
367 }
368
369 bool DOMWindow::canShowModalDialog(const Frame* frame)
370 {
371     if (!frame)
372         return false;
373     Page* page = frame->page();
374     if (!page)
375         return false;
376     return page->chrome().canRunModal();
377 }
378
379 bool DOMWindow::canShowModalDialogNow(const Frame* frame)
380 {
381     if (!frame)
382         return false;
383     Page* page = frame->page();
384     if (!page)
385         return false;
386     return page->chrome().canRunModalNow();
387 }
388
389 DOMWindow::DOMWindow(Document* document)
390     : ContextDestructionObserver(document)
391     , FrameDestructionObserver(document->frame())
392     , m_shouldPrintWhenFinishedLoading(false)
393     , m_suspendedForPageCache(false)
394 {
395     ASSERT(frame());
396     ASSERT(DOMWindow::document());
397 }
398
399 void DOMWindow::didSecureTransitionTo(Document* document)
400 {
401     observeContext(document);
402 }
403
404 DOMWindow::~DOMWindow()
405 {
406 #ifndef NDEBUG
407     if (!m_suspendedForPageCache) {
408         ASSERT(!m_screen);
409         ASSERT(!m_history);
410         ASSERT(!m_crypto);
411         ASSERT(!m_locationbar);
412         ASSERT(!m_menubar);
413         ASSERT(!m_personalbar);
414         ASSERT(!m_scrollbars);
415         ASSERT(!m_statusbar);
416         ASSERT(!m_toolbar);
417         ASSERT(!m_console);
418         ASSERT(!m_navigator);
419 #if ENABLE(WEB_TIMING)
420         ASSERT(!m_performance);
421 #endif
422         ASSERT(!m_location);
423         ASSERT(!m_media);
424         ASSERT(!m_sessionStorage);
425         ASSERT(!m_localStorage);
426         ASSERT(!m_applicationCache);
427     }
428 #endif
429
430     if (m_suspendedForPageCache)
431         willDestroyCachedFrame();
432     else
433         willDestroyDocumentInFrame();
434
435     // As the ASSERTs above indicate, this reset should only be necessary if this DOMWindow is suspended for the page cache.
436     // But we don't want to risk any of these objects hanging around after we've been destroyed.
437     resetDOMWindowProperties();
438
439     removeAllUnloadEventListeners(this);
440     removeAllBeforeUnloadEventListeners(this);
441 }
442
443 const AtomicString& DOMWindow::interfaceName() const
444 {
445     return eventNames().interfaceForDOMWindow;
446 }
447
448 ScriptExecutionContext* DOMWindow::scriptExecutionContext() const
449 {
450     return ContextDestructionObserver::scriptExecutionContext();
451 }
452
453 DOMWindow* DOMWindow::toDOMWindow()
454 {
455     return this;
456 }
457
458 PassRefPtr<MediaQueryList> DOMWindow::matchMedia(const String& media)
459 {
460     return document() ? document()->mediaQueryMatcher().matchMedia(media) : 0;
461 }
462
463 Page* DOMWindow::page()
464 {
465     return frame() ? frame()->page() : 0;
466 }
467
468 void DOMWindow::frameDestroyed()
469 {
470     willDestroyDocumentInFrame();
471     FrameDestructionObserver::frameDestroyed();
472     resetDOMWindowProperties();
473 }
474
475 void DOMWindow::willDetachPage()
476 {
477     InspectorInstrumentation::frameWindowDiscarded(m_frame, this);
478 }
479
480 void DOMWindow::willDestroyCachedFrame()
481 {
482     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
483     // unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInCachedFrame.
484     Vector<DOMWindowProperty*> properties;
485     copyToVector(m_properties, properties);
486     for (size_t i = 0; i < properties.size(); ++i)
487         properties[i]->willDestroyGlobalObjectInCachedFrame();
488 }
489
490 void DOMWindow::willDestroyDocumentInFrame()
491 {
492     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
493     // unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInFrame.
494     Vector<DOMWindowProperty*> properties;
495     copyToVector(m_properties, properties);
496     for (size_t i = 0; i < properties.size(); ++i)
497         properties[i]->willDestroyGlobalObjectInFrame();
498 }
499
500 void DOMWindow::willDetachDocumentFromFrame()
501 {
502     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
503     // unregister themselves from the DOMWindow as a result of the call to willDetachGlobalObjectFromFrame.
504     Vector<DOMWindowProperty*> properties;
505     copyToVector(m_properties, properties);
506     for (size_t i = 0; i < properties.size(); ++i)
507         properties[i]->willDetachGlobalObjectFromFrame();
508 }
509
510 void DOMWindow::registerProperty(DOMWindowProperty* property)
511 {
512     m_properties.add(property);
513 }
514
515 void DOMWindow::unregisterProperty(DOMWindowProperty* property)
516 {
517     m_properties.remove(property);
518 }
519
520 void DOMWindow::resetUnlessSuspendedForPageCache()
521 {
522     if (m_suspendedForPageCache)
523         return;
524     willDestroyDocumentInFrame();
525     resetDOMWindowProperties();
526 }
527
528 void DOMWindow::suspendForPageCache()
529 {
530     disconnectDOMWindowProperties();
531     m_suspendedForPageCache = true;
532 }
533
534 void DOMWindow::resumeFromPageCache()
535 {
536     reconnectDOMWindowProperties();
537     m_suspendedForPageCache = false;
538 }
539
540 void DOMWindow::disconnectDOMWindowProperties()
541 {
542     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
543     // unregister themselves from the DOMWindow as a result of the call to disconnectFrameForPageCache.
544     Vector<DOMWindowProperty*> properties;
545     copyToVector(m_properties, properties);
546     for (size_t i = 0; i < properties.size(); ++i)
547         properties[i]->disconnectFrameForPageCache();
548 }
549
550 void DOMWindow::reconnectDOMWindowProperties()
551 {
552     ASSERT(m_suspendedForPageCache);
553     // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
554     // unregister themselves from the DOMWindow as a result of the call to reconnectFromPageCache.
555     Vector<DOMWindowProperty*> properties;
556     copyToVector(m_properties, properties);
557     for (size_t i = 0; i < properties.size(); ++i)
558         properties[i]->reconnectFrameFromPageCache(m_frame);
559 }
560
561 void DOMWindow::resetDOMWindowProperties()
562 {
563     m_properties.clear();
564
565     m_screen = 0;
566     m_history = 0;
567     m_crypto = 0;
568     m_locationbar = 0;
569     m_menubar = 0;
570     m_personalbar = 0;
571     m_scrollbars = 0;
572     m_statusbar = 0;
573     m_toolbar = 0;
574     m_console = 0;
575     m_navigator = 0;
576 #if ENABLE(WEB_TIMING)
577     m_performance = 0;
578 #endif
579     m_location = 0;
580     m_media = 0;
581     m_sessionStorage = 0;
582     m_localStorage = 0;
583     m_applicationCache = 0;
584 }
585
586 bool DOMWindow::isCurrentlyDisplayedInFrame() const
587 {
588     return m_frame && m_frame->document()->domWindow() == this;
589 }
590
591 #if ENABLE(ORIENTATION_EVENTS)
592 int DOMWindow::orientation() const
593 {
594     if (!m_frame)
595         return 0;
596
597     return m_frame->orientation();
598 }
599 #endif
600
601 Screen* DOMWindow::screen() const
602 {
603     if (!isCurrentlyDisplayedInFrame())
604         return 0;
605     if (!m_screen)
606         m_screen = Screen::create(m_frame);
607     return m_screen.get();
608 }
609
610 History* DOMWindow::history() const
611 {
612     if (!isCurrentlyDisplayedInFrame())
613         return 0;
614     if (!m_history)
615         m_history = History::create(m_frame);
616     return m_history.get();
617 }
618
619 Crypto* DOMWindow::crypto() const
620 {
621     if (!isCurrentlyDisplayedInFrame())
622         return 0;
623     if (!m_crypto)
624         m_crypto = Crypto::create();
625     return m_crypto.get();
626 }
627
628 BarProp* DOMWindow::locationbar() const
629 {
630     if (!isCurrentlyDisplayedInFrame())
631         return 0;
632     if (!m_locationbar)
633         m_locationbar = BarProp::create(m_frame, BarProp::Locationbar);
634     return m_locationbar.get();
635 }
636
637 BarProp* DOMWindow::menubar() const
638 {
639     if (!isCurrentlyDisplayedInFrame())
640         return 0;
641     if (!m_menubar)
642         m_menubar = BarProp::create(m_frame, BarProp::Menubar);
643     return m_menubar.get();
644 }
645
646 BarProp* DOMWindow::personalbar() const
647 {
648     if (!isCurrentlyDisplayedInFrame())
649         return 0;
650     if (!m_personalbar)
651         m_personalbar = BarProp::create(m_frame, BarProp::Personalbar);
652     return m_personalbar.get();
653 }
654
655 BarProp* DOMWindow::scrollbars() const
656 {
657     if (!isCurrentlyDisplayedInFrame())
658         return 0;
659     if (!m_scrollbars)
660         m_scrollbars = BarProp::create(m_frame, BarProp::Scrollbars);
661     return m_scrollbars.get();
662 }
663
664 BarProp* DOMWindow::statusbar() const
665 {
666     if (!isCurrentlyDisplayedInFrame())
667         return 0;
668     if (!m_statusbar)
669         m_statusbar = BarProp::create(m_frame, BarProp::Statusbar);
670     return m_statusbar.get();
671 }
672
673 BarProp* DOMWindow::toolbar() const
674 {
675     if (!isCurrentlyDisplayedInFrame())
676         return 0;
677     if (!m_toolbar)
678         m_toolbar = BarProp::create(m_frame, BarProp::Toolbar);
679     return m_toolbar.get();
680 }
681
682 Console* DOMWindow::console() const
683 {
684     if (!isCurrentlyDisplayedInFrame())
685         return 0;
686     if (!m_console)
687         m_console = Console::create(m_frame);
688     return m_console.get();
689 }
690
691 PageConsole* DOMWindow::pageConsole() const
692 {
693     if (!isCurrentlyDisplayedInFrame())
694         return 0;
695     return m_frame->page() ? m_frame->page()->console() : 0;
696 }
697
698 DOMApplicationCache* DOMWindow::applicationCache() const
699 {
700     if (!isCurrentlyDisplayedInFrame())
701         return 0;
702     if (!m_applicationCache)
703         m_applicationCache = DOMApplicationCache::create(m_frame);
704     return m_applicationCache.get();
705 }
706
707 Navigator* DOMWindow::navigator() const
708 {
709     if (!isCurrentlyDisplayedInFrame())
710         return 0;
711     if (!m_navigator)
712         m_navigator = Navigator::create(m_frame);
713     return m_navigator.get();
714 }
715
716 #if ENABLE(WEB_TIMING)
717 Performance* DOMWindow::performance() const
718 {
719     if (!isCurrentlyDisplayedInFrame())
720         return 0;
721     if (!m_performance)
722         m_performance = Performance::create(m_frame);
723     return m_performance.get();
724 }
725 #endif
726
727 Location* DOMWindow::location() const
728 {
729     if (!isCurrentlyDisplayedInFrame())
730         return 0;
731     if (!m_location)
732         m_location = Location::create(m_frame);
733     return m_location.get();
734 }
735
736 Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const
737 {
738     if (!isCurrentlyDisplayedInFrame())
739         return 0;
740
741     Document* document = this->document();
742     if (!document)
743         return 0;
744
745     if (!document->securityOrigin()->canAccessSessionStorage(document->topOrigin())) {
746         ec = SECURITY_ERR;
747         return 0;
748     }
749
750     if (m_sessionStorage) {
751         if (!m_sessionStorage->area().canAccessStorage(m_frame)) {
752             ec = SECURITY_ERR;
753             return 0;
754         }
755         return m_sessionStorage.get();
756     }
757
758     Page* page = document->page();
759     if (!page)
760         return 0;
761
762     RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
763     if (!storageArea->canAccessStorage(m_frame)) {
764         ec = SECURITY_ERR;
765         return 0;
766     }
767
768     m_sessionStorage = Storage::create(m_frame, storageArea.release());
769     return m_sessionStorage.get();
770 }
771
772 Storage* DOMWindow::localStorage(ExceptionCode& ec) const
773 {
774     if (!isCurrentlyDisplayedInFrame())
775         return 0;
776
777     Document* document = this->document();
778     if (!document)
779         return 0;
780
781     if (!document->securityOrigin()->canAccessLocalStorage(0)) {
782         ec = SECURITY_ERR;
783         return 0;
784     }
785
786     if (m_localStorage) {
787         if (!m_localStorage->area().canAccessStorage(m_frame)) {
788             ec = SECURITY_ERR;
789             return 0;
790         }
791         return m_localStorage.get();
792     }
793
794     Page* page = document->page();
795     if (!page)
796         return 0;
797
798     if (!page->settings()->localStorageEnabled())
799         return 0;
800
801     RefPtr<StorageArea> storageArea;
802     if (!document->securityOrigin()->canAccessLocalStorage(document->topOrigin()))
803         storageArea = page->group().transientLocalStorage(document->topOrigin())->storageArea(document->securityOrigin());
804     else
805         storageArea = page->group().localStorage()->storageArea(document->securityOrigin());
806
807     if (!storageArea->canAccessStorage(m_frame)) {
808         ec = SECURITY_ERR;
809         return 0;
810     }
811
812     m_localStorage = Storage::create(m_frame, storageArea.release());
813     return m_localStorage.get();
814 }
815
816 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
817 {
818     MessagePortArray ports;
819     if (port)
820         ports.append(port);
821     postMessage(message, &ports, targetOrigin, source, ec);
822 }
823
824 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
825 {
826     if (!isCurrentlyDisplayedInFrame())
827         return;
828
829     Document* sourceDocument = source->document();
830
831     // Compute the target origin.  We need to do this synchronously in order
832     // to generate the SYNTAX_ERR exception correctly.
833     RefPtr<SecurityOrigin> target;
834     if (targetOrigin == "/") {
835         if (!sourceDocument)
836             return;
837         target = sourceDocument->securityOrigin();
838     } else if (targetOrigin != "*") {
839         target = SecurityOrigin::createFromString(targetOrigin);
840         // It doesn't make sense target a postMessage at a unique origin
841         // because there's no way to represent a unique origin in a string.
842         if (target->isUnique()) {
843             ec = SYNTAX_ERR;
844             return;
845         }
846     }
847
848     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec);
849     if (ec)
850         return;
851
852     // Capture the source of the message.  We need to do this synchronously
853     // in order to capture the source of the message correctly.
854     if (!sourceDocument)
855         return;
856     String sourceOrigin = sourceDocument->securityOrigin()->toString();
857
858     // Capture stack trace only when inspector front-end is loaded as it may be time consuming.
859     RefPtr<ScriptCallStack> stackTrace;
860     if (InspectorInstrumentation::consoleAgentEnabled(sourceDocument))
861         stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
862
863     // Schedule the message.
864     PostMessageTimer* timer = new PostMessageTimer(this, message, sourceOrigin, source, channels.release(), target.get(), stackTrace.release());
865     timer->startOneShot(0);
866 }
867
868 void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t)
869 {
870     OwnPtr<PostMessageTimer> timer(t);
871
872     if (!document() || !isCurrentlyDisplayedInFrame())
873         return;
874
875     RefPtr<MessageEvent> event = timer->event(document());
876
877     // Give the embedder a chance to intercept this postMessage because this
878     // DOMWindow might be a proxy for another in browsers that support
879     // postMessage calls across WebKit instances.
880     if (m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get()))
881         return;
882
883     dispatchMessageEventWithOriginCheck(timer->targetOrigin(), event, timer->stackTrace());
884 }
885
886 void DOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtr<Event> event, PassRefPtr<ScriptCallStack> stackTrace)
887 {
888     if (intendedTargetOrigin) {
889         // Check target origin now since the target document may have changed since the timer was scheduled.
890         if (!intendedTargetOrigin->isSameSchemeHostPort(document()->securityOrigin())) {
891             String message = "Unable to post message to " + intendedTargetOrigin->toString() +
892                              ". Recipient has origin " + document()->securityOrigin()->toString() + ".\n";
893             pageConsole()->addMessage(SecurityMessageSource, ErrorMessageLevel, message, stackTrace);
894             return;
895         }
896     }
897
898     dispatchEvent(event);
899 }
900
901 DOMSelection* DOMWindow::getSelection()
902 {
903     if (!isCurrentlyDisplayedInFrame() || !m_frame)
904         return 0;
905
906     return m_frame->document()->getSelection();
907 }
908
909 Element* DOMWindow::frameElement() const
910 {
911     if (!m_frame)
912         return 0;
913
914     return m_frame->ownerElement();
915 }
916
917 void DOMWindow::focus(ScriptExecutionContext* context)
918 {
919     if (!m_frame)
920         return;
921
922     Page* page = m_frame->page();
923     if (!page)
924         return;
925
926     bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed() || !m_frame->settings()->windowFocusRestricted();
927     if (context) {
928         ASSERT(isMainThread());
929         Document* activeDocument = toDocument(context);
930         if (opener() && opener() != this && activeDocument->domWindow() == opener())
931             allowFocus = true;
932     }
933
934     // If we're a top level window, bring the window to the front.
935     if (m_frame == page->mainFrame() && allowFocus)
936         page->chrome().focus();
937
938     if (!m_frame)
939         return;
940
941     // Clear the current frame's focused node if a new frame is about to be focused.
942     Frame* focusedFrame = page->focusController()->focusedFrame();
943     if (focusedFrame && focusedFrame != m_frame)
944         focusedFrame->document()->setFocusedElement(0);
945
946     m_frame->eventHandler()->focusDocumentView();
947 }
948
949 void DOMWindow::blur()
950 {
951
952     if (!m_frame)
953         return;
954
955     Page* page = m_frame->page();
956     if (!page)
957         return;
958
959     if (m_frame->settings()->windowFocusRestricted())
960         return;
961
962     if (m_frame != page->mainFrame())
963         return;
964
965     page->chrome().unfocus();
966 }
967
968 void DOMWindow::close(ScriptExecutionContext* context)
969 {
970     if (!m_frame)
971         return;
972
973     Page* page = m_frame->page();
974     if (!page)
975         return;
976
977     if (m_frame != page->mainFrame())
978         return;
979
980     if (context) {
981         ASSERT(isMainThread());
982         Document* activeDocument = toDocument(context);
983         if (!activeDocument)
984             return;
985
986         if (!activeDocument->canNavigate(m_frame))
987             return;
988     }
989
990     Settings* settings = m_frame->settings();
991     bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows();
992
993     if (!(page->openedByDOM() || page->backForward()->count() <= 1 || allowScriptsToCloseWindows))
994         return;
995
996     if (!m_frame->loader()->shouldClose())
997         return;
998
999     page->chrome().closeWindowSoon();
1000 }
1001
1002 void DOMWindow::print()
1003 {
1004     if (!m_frame)
1005         return;
1006
1007     Page* page = m_frame->page();
1008     if (!page)
1009         return;
1010
1011     // Pages are not allowed to bring up a modal print dialog during BeforeUnload dispatch.
1012     if (page->isAnyFrameHandlingBeforeUnloadEvent()) {
1013         printErrorMessage("Use of window.print is not allowed during beforeunload event dispatch.");
1014         return;
1015     }
1016
1017     if (m_frame->loader()->activeDocumentLoader()->isLoading()) {
1018         m_shouldPrintWhenFinishedLoading = true;
1019         return;
1020     }
1021     m_shouldPrintWhenFinishedLoading = false;
1022     page->chrome().print(m_frame);
1023 }
1024
1025 void DOMWindow::stop()
1026 {
1027     if (!m_frame)
1028         return;
1029
1030     // We must check whether the load is complete asynchronously, because we might still be parsing
1031     // the document until the callstack unwinds.
1032     m_frame->loader()->stopForUserCancel(true);
1033 }
1034
1035 void DOMWindow::alert(const String& message)
1036 {
1037     if (!m_frame)
1038         return;
1039
1040     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
1041     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
1042         printErrorMessage("Use of window.alert is not allowed during beforeunload event dispatch.");
1043         return;
1044     }
1045
1046     m_frame->document()->updateStyleIfNeeded();
1047
1048     Page* page = m_frame->page();
1049     if (!page)
1050         return;
1051
1052     page->chrome().runJavaScriptAlert(m_frame, message);
1053 }
1054
1055 bool DOMWindow::confirm(const String& message)
1056 {
1057     if (!m_frame)
1058         return false;
1059     
1060     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
1061     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
1062         printErrorMessage("Use of window.confirm is not allowed during beforeunload event dispatch.");
1063         return false;
1064     }
1065
1066     m_frame->document()->updateStyleIfNeeded();
1067
1068     Page* page = m_frame->page();
1069     if (!page)
1070         return false;
1071
1072     return page->chrome().runJavaScriptConfirm(m_frame, message);
1073 }
1074
1075 String DOMWindow::prompt(const String& message, const String& defaultValue)
1076 {
1077     if (!m_frame)
1078         return String();
1079
1080     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
1081     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
1082         printErrorMessage("Use of window.prompt is not allowed during beforeunload event dispatch.");
1083         return String();
1084     }
1085
1086     m_frame->document()->updateStyleIfNeeded();
1087
1088     Page* page = m_frame->page();
1089     if (!page)
1090         return String();
1091
1092     String returnValue;
1093     if (page->chrome().runJavaScriptPrompt(m_frame, message, defaultValue, returnValue))
1094         return returnValue;
1095
1096     return String();
1097 }
1098
1099 String DOMWindow::btoa(const String& stringToEncode, ExceptionCode& ec)
1100 {
1101     if (stringToEncode.isNull())
1102         return String();
1103
1104     if (!stringToEncode.containsOnlyLatin1()) {
1105         ec = INVALID_CHARACTER_ERR;
1106         return String();
1107     }
1108
1109     return base64Encode(stringToEncode.latin1());
1110 }
1111
1112 String DOMWindow::atob(const String& encodedString, ExceptionCode& ec)
1113 {
1114     if (encodedString.isNull())
1115         return String();
1116
1117     if (!encodedString.containsOnlyLatin1()) {
1118         ec = INVALID_CHARACTER_ERR;
1119         return String();
1120     }
1121
1122     Vector<char> out;
1123     if (!base64Decode(encodedString, out, Base64FailOnInvalidCharacterOrExcessPadding)) {
1124         ec = INVALID_CHARACTER_ERR;
1125         return String();
1126     }
1127
1128     return String(out.data(), out.size());
1129 }
1130
1131 bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const
1132 {
1133     if (!isCurrentlyDisplayedInFrame())
1134         return false;
1135
1136     // FIXME (13016): Support wholeWord, searchInFrames and showDialog
1137     return m_frame->editor().findString(string, !backwards, caseSensitive, wrap, false);
1138 }
1139
1140 bool DOMWindow::offscreenBuffering() const
1141 {
1142     return true;
1143 }
1144
1145 int DOMWindow::outerHeight() const
1146 {
1147     if (!m_frame)
1148         return 0;
1149
1150     Page* page = m_frame->page();
1151     if (!page)
1152         return 0;
1153
1154     return static_cast<int>(page->chrome().windowRect().height());
1155 }
1156
1157 int DOMWindow::outerWidth() const
1158 {
1159     if (!m_frame)
1160         return 0;
1161
1162     Page* page = m_frame->page();
1163     if (!page)
1164         return 0;
1165
1166     return static_cast<int>(page->chrome().windowRect().width());
1167 }
1168
1169 int DOMWindow::innerHeight() const
1170 {
1171     if (!m_frame)
1172         return 0;
1173
1174     FrameView* view = m_frame->view();
1175     if (!view)
1176         return 0;
1177
1178     // If the device height is overridden, do not include the horizontal scrollbar into the innerHeight (since it is absent on the real device).
1179     bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenHeightOverride(m_frame);
1180     return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRect(includeScrollbars ? ScrollableArea::IncludeScrollbars : ScrollableArea::ExcludeScrollbars).height()));
1181 }
1182
1183 int DOMWindow::innerWidth() const
1184 {
1185     if (!m_frame)
1186         return 0;
1187
1188     FrameView* view = m_frame->view();
1189     if (!view)
1190         return 0;
1191
1192     // If the device width is overridden, do not include the vertical scrollbar into the innerWidth (since it is absent on the real device).
1193     bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(m_frame);
1194     return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRect(includeScrollbars ? ScrollableArea::IncludeScrollbars : ScrollableArea::ExcludeScrollbars).width()));
1195 }
1196
1197 int DOMWindow::screenX() const
1198 {
1199     if (!m_frame)
1200         return 0;
1201
1202     Page* page = m_frame->page();
1203     if (!page)
1204         return 0;
1205
1206     return static_cast<int>(page->chrome().windowRect().x());
1207 }
1208
1209 int DOMWindow::screenY() const
1210 {
1211     if (!m_frame)
1212         return 0;
1213
1214     Page* page = m_frame->page();
1215     if (!page)
1216         return 0;
1217
1218     return static_cast<int>(page->chrome().windowRect().y());
1219 }
1220
1221 int DOMWindow::scrollX() const
1222 {
1223     if (!m_frame)
1224         return 0;
1225
1226     FrameView* view = m_frame->view();
1227     if (!view)
1228         return 0;
1229
1230     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1231
1232     return view->mapFromLayoutToCSSUnits(view->scrollX());
1233 }
1234
1235 int DOMWindow::scrollY() const
1236 {
1237     if (!m_frame)
1238         return 0;
1239
1240     FrameView* view = m_frame->view();
1241     if (!view)
1242         return 0;
1243
1244     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1245
1246     return view->mapFromLayoutToCSSUnits(view->scrollY());
1247 }
1248
1249 bool DOMWindow::closed() const
1250 {
1251     return !m_frame;
1252 }
1253
1254 unsigned DOMWindow::length() const
1255 {
1256     if (!isCurrentlyDisplayedInFrame())
1257         return 0;
1258
1259     return m_frame->tree()->scopedChildCount();
1260 }
1261
1262 String DOMWindow::name() const
1263 {
1264     if (!m_frame)
1265         return String();
1266
1267     return m_frame->tree()->name();
1268 }
1269
1270 void DOMWindow::setName(const String& string)
1271 {
1272     if (!m_frame)
1273         return;
1274
1275     m_frame->tree()->setName(string);
1276     m_frame->loader()->client()->didChangeName(string);
1277 }
1278
1279 void DOMWindow::setStatus(const String& string) 
1280 {
1281     m_status = string;
1282
1283     if (!m_frame)
1284         return;
1285
1286     Page* page = m_frame->page();
1287     if (!page)
1288         return;
1289
1290     ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1291     page->chrome().setStatusbarText(m_frame, m_status);
1292
1293     
1294 void DOMWindow::setDefaultStatus(const String& string) 
1295 {
1296     m_defaultStatus = string;
1297
1298     if (!m_frame)
1299         return;
1300
1301     Page* page = m_frame->page();
1302     if (!page)
1303         return;
1304
1305     ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1306     page->chrome().setStatusbarText(m_frame, m_defaultStatus);
1307 }
1308
1309 DOMWindow* DOMWindow::self() const
1310 {
1311     if (!m_frame)
1312         return 0;
1313
1314     return m_frame->document()->domWindow();
1315 }
1316
1317 DOMWindow* DOMWindow::opener() const
1318 {
1319     if (!m_frame)
1320         return 0;
1321
1322     Frame* opener = m_frame->loader()->opener();
1323     if (!opener)
1324         return 0;
1325
1326     return opener->document()->domWindow();
1327 }
1328
1329 DOMWindow* DOMWindow::parent() const
1330 {
1331     if (!m_frame)
1332         return 0;
1333
1334     Frame* parent = m_frame->tree()->parent();
1335     if (parent)
1336         return parent->document()->domWindow();
1337
1338     return m_frame->document()->domWindow();
1339 }
1340
1341 DOMWindow* DOMWindow::top() const
1342 {
1343     if (!m_frame)
1344         return 0;
1345
1346     Page* page = m_frame->page();
1347     if (!page)
1348         return 0;
1349
1350     return m_frame->tree()->top()->document()->domWindow();
1351 }
1352
1353 Document* DOMWindow::document() const
1354 {
1355     ScriptExecutionContext* context = ContextDestructionObserver::scriptExecutionContext();
1356     return toDocument(context);
1357 }
1358
1359 PassRefPtr<StyleMedia> DOMWindow::styleMedia() const
1360 {
1361     if (!isCurrentlyDisplayedInFrame())
1362         return 0;
1363     if (!m_media)
1364         m_media = StyleMedia::create(m_frame);
1365     return m_media.get();
1366 }
1367
1368 PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const
1369 {
1370     if (!elt)
1371         return 0;
1372
1373     return CSSComputedStyleDeclaration::create(elt, false, pseudoElt);
1374 }
1375
1376 PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement, bool authorOnly) const
1377 {
1378     if (!isCurrentlyDisplayedInFrame())
1379         return 0;
1380
1381     unsigned colonStart = pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0;
1382     CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(AtomicString(pseudoElement.substring(colonStart)));
1383     if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty())
1384         return 0;
1385
1386     unsigned rulesToInclude = StyleResolver::AuthorCSSRules;
1387     if (!authorOnly)
1388         rulesToInclude |= StyleResolver::UAAndUserCSSRules;
1389     if (Settings* settings = m_frame->settings()) {
1390         if (settings->crossOriginCheckInGetMatchedCSSRulesDisabled())
1391             rulesToInclude |= StyleResolver::CrossOriginCSSRules;
1392     }
1393
1394     PseudoId pseudoId = CSSSelector::pseudoId(pseudoType);
1395
1396     Vector<RefPtr<StyleRuleBase> > matchedRules = m_frame->document()->ensureStyleResolver().pseudoStyleRulesForElement(element, pseudoId, rulesToInclude);
1397     if (matchedRules.isEmpty())
1398         return 0;
1399
1400     RefPtr<StaticCSSRuleList> ruleList = StaticCSSRuleList::create();
1401     for (unsigned i = 0; i < matchedRules.size(); ++i)
1402         ruleList->rules().append(matchedRules[i]->createCSSOMWrapper());
1403
1404     return ruleList.release();
1405 }
1406
1407 PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const
1408 {
1409     if (!node || !p)
1410         return 0;
1411
1412     if (!document())
1413         return 0;
1414
1415     document()->updateLayoutIgnorePendingStylesheets();
1416
1417     FloatPoint pagePoint(p->x(), p->y());
1418     pagePoint = node->convertToPage(pagePoint);
1419     return WebKitPoint::create(pagePoint.x(), pagePoint.y());
1420 }
1421
1422 PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const
1423 {
1424     if (!node || !p)
1425         return 0;
1426
1427     if (!document())
1428         return 0;
1429
1430     document()->updateLayoutIgnorePendingStylesheets();
1431
1432     FloatPoint nodePoint(p->x(), p->y());
1433     nodePoint = node->convertFromPage(nodePoint);
1434     return WebKitPoint::create(nodePoint.x(), nodePoint.y());
1435 }
1436
1437 double DOMWindow::devicePixelRatio() const
1438 {
1439     if (!m_frame)
1440         return 0.0;
1441
1442     Page* page = m_frame->page();
1443     if (!page)
1444         return 0.0;
1445
1446     return page->deviceScaleFactor();
1447 }
1448
1449 void DOMWindow::scrollBy(int x, int y) const
1450 {
1451     if (!isCurrentlyDisplayedInFrame())
1452         return;
1453
1454     document()->updateLayoutIgnorePendingStylesheets();
1455
1456     FrameView* view = m_frame->view();
1457     if (!view)
1458         return;
1459
1460     IntSize scaledOffset(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
1461     view->scrollBy(scaledOffset);
1462 }
1463
1464 void DOMWindow::scrollTo(int x, int y) const
1465 {
1466     if (!isCurrentlyDisplayedInFrame())
1467         return;
1468
1469     document()->updateLayoutIgnorePendingStylesheets();
1470
1471     RefPtr<FrameView> view = m_frame->view();
1472     if (!view)
1473         return;
1474
1475     IntPoint layoutPos(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
1476     view->setScrollPosition(layoutPos);
1477 }
1478
1479 bool DOMWindow::allowedToChangeWindowGeometry() const
1480 {
1481     if (!m_frame)
1482         return false;
1483     const Page* page = m_frame->page();
1484     if (!page)
1485         return false;
1486     if (m_frame != page->mainFrame())
1487         return false;
1488     // Prevent web content from tricking the user into initiating a drag.
1489     if (m_frame->eventHandler()->mousePressed())
1490         return false;
1491     return true;
1492 }
1493
1494 void DOMWindow::moveBy(float x, float y) const
1495 {
1496     if (!allowedToChangeWindowGeometry())
1497         return;
1498
1499     Page* page = m_frame->page();
1500     FloatRect fr = page->chrome().windowRect();
1501     FloatRect update = fr;
1502     update.move(x, y);
1503     // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1504     page->chrome().setWindowRect(adjustWindowRect(page, update));
1505 }
1506
1507 void DOMWindow::moveTo(float x, float y) const
1508 {
1509     if (!allowedToChangeWindowGeometry())
1510         return;
1511
1512     Page* page = m_frame->page();
1513     FloatRect fr = page->chrome().windowRect();
1514     FloatRect sr = screenAvailableRect(page->mainFrame()->view());
1515     fr.setLocation(sr.location());
1516     FloatRect update = fr;
1517     update.move(x, y);
1518     // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1519     page->chrome().setWindowRect(adjustWindowRect(page, update));
1520 }
1521
1522 void DOMWindow::resizeBy(float x, float y) const
1523 {
1524     if (!allowedToChangeWindowGeometry())
1525         return;
1526
1527     Page* page = m_frame->page();
1528     FloatRect fr = page->chrome().windowRect();
1529     FloatSize dest = fr.size() + FloatSize(x, y);
1530     FloatRect update(fr.location(), dest);
1531     page->chrome().setWindowRect(adjustWindowRect(page, update));
1532 }
1533
1534 void DOMWindow::resizeTo(float width, float height) const
1535 {
1536     if (!allowedToChangeWindowGeometry())
1537         return;
1538
1539     Page* page = m_frame->page();
1540     FloatRect fr = page->chrome().windowRect();
1541     FloatSize dest = FloatSize(width, height);
1542     FloatRect update(fr.location(), dest);
1543     page->chrome().setWindowRect(adjustWindowRect(page, update));
1544 }
1545
1546 int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
1547 {
1548     ScriptExecutionContext* context = scriptExecutionContext();
1549     if (!context) {
1550         ec = INVALID_ACCESS_ERR;
1551         return -1;
1552     }
1553     return DOMTimer::install(context, action, timeout, true);
1554 }
1555
1556 void DOMWindow::clearTimeout(int timeoutId)
1557 {
1558     ScriptExecutionContext* context = scriptExecutionContext();
1559     if (!context)
1560         return;
1561     DOMTimer::removeById(context, timeoutId);
1562 }
1563
1564 int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
1565 {
1566     ScriptExecutionContext* context = scriptExecutionContext();
1567     if (!context) {
1568         ec = INVALID_ACCESS_ERR;
1569         return -1;
1570     }
1571     return DOMTimer::install(context, action, timeout, false);
1572 }
1573
1574 void DOMWindow::clearInterval(int timeoutId)
1575 {
1576     ScriptExecutionContext* context = scriptExecutionContext();
1577     if (!context)
1578         return;
1579     DOMTimer::removeById(context, timeoutId);
1580 }
1581
1582 #if ENABLE(REQUEST_ANIMATION_FRAME)
1583 int DOMWindow::requestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
1584 {
1585     callback->m_useLegacyTimeBase = false;
1586     if (Document* d = document())
1587         return d->requestAnimationFrame(callback);
1588     return 0;
1589 }
1590
1591 int DOMWindow::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
1592 {
1593     callback->m_useLegacyTimeBase = true;
1594     if (Document* d = document())
1595         return d->requestAnimationFrame(callback);
1596     return 0;
1597 }
1598
1599 void DOMWindow::cancelAnimationFrame(int id)
1600 {
1601     if (Document* d = document())
1602         d->cancelAnimationFrame(id);
1603 }
1604 #endif
1605
1606 #if ENABLE(CSS3_CONDITIONAL_RULES)
1607 DOMWindowCSS* DOMWindow::css()
1608 {
1609     if (!m_css)
1610         m_css = DOMWindowCSS::create();
1611     return m_css.get();
1612 }
1613 #endif
1614
1615 static void didAddStorageEventListener(DOMWindow* window)
1616 {
1617     // Creating these WebCore::Storage objects informs the system that we'd like to receive
1618     // notifications about storage events that might be triggered in other processes. Rather
1619     // than subscribe to these notifications explicitly, we subscribe to them implicitly to
1620     // simplify the work done by the system. 
1621     window->localStorage(IGNORE_EXCEPTION);
1622     window->sessionStorage(IGNORE_EXCEPTION);
1623 }
1624
1625 bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1626 {
1627     if (!EventTarget::addEventListener(eventType, listener, useCapture))
1628         return false;
1629
1630     if (Document* document = this->document()) {
1631         document->addListenerTypeIfNeeded(eventType);
1632         if (eventType == eventNames().mousewheelEvent)
1633             document->didAddWheelEventHandler();
1634         else if (eventNames().isTouchEventType(eventType))
1635             document->didAddTouchEventHandler(document);
1636         else if (eventType == eventNames().storageEvent)
1637             didAddStorageEventListener(this);
1638     }
1639
1640     if (eventType == eventNames().unloadEvent)
1641         addUnloadEventListener(this);
1642     else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
1643         addBeforeUnloadEventListener(this);
1644 #if ENABLE(DEVICE_ORIENTATION)
1645     else if (eventType == eventNames().devicemotionEvent && RuntimeEnabledFeatures::deviceMotionEnabled()) {
1646         if (DeviceMotionController* controller = DeviceMotionController::from(page()))
1647             controller->addDeviceEventListener(this);
1648     } else if (eventType == eventNames().deviceorientationEvent && RuntimeEnabledFeatures::deviceOrientationEnabled()) {
1649         if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
1650             controller->addDeviceEventListener(this);
1651     }
1652 #endif
1653
1654 #if ENABLE(PROXIMITY_EVENTS)
1655     else if (eventType == eventNames().webkitdeviceproximityEvent) {
1656         if (DeviceProximityController* controller = DeviceProximityController::from(page()))
1657             controller->addDeviceEventListener(this);
1658     }
1659 #endif
1660
1661     return true;
1662 }
1663
1664 bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
1665 {
1666     if (!EventTarget::removeEventListener(eventType, listener, useCapture))
1667         return false;
1668
1669     if (Document* document = this->document()) {
1670         if (eventType == eventNames().mousewheelEvent)
1671             document->didRemoveWheelEventHandler();
1672         else if (eventNames().isTouchEventType(eventType))
1673             document->didRemoveTouchEventHandler(document);
1674     }
1675
1676     if (eventType == eventNames().unloadEvent)
1677         removeUnloadEventListener(this);
1678     else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
1679         removeBeforeUnloadEventListener(this);
1680 #if ENABLE(DEVICE_ORIENTATION)
1681     else if (eventType == eventNames().devicemotionEvent) {
1682         if (DeviceMotionController* controller = DeviceMotionController::from(page()))
1683             controller->removeDeviceEventListener(this);
1684     } else if (eventType == eventNames().deviceorientationEvent) {
1685         if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
1686             controller->removeDeviceEventListener(this);
1687     }
1688 #endif
1689
1690 #if ENABLE(PROXIMITY_EVENTS)
1691     else if (eventType == eventNames().webkitdeviceproximityEvent) {
1692         if (DeviceProximityController* controller = DeviceProximityController::from(page()))
1693             controller->removeDeviceEventListener(this);
1694     }
1695 #endif
1696
1697     return true;
1698 }
1699
1700 void DOMWindow::dispatchLoadEvent()
1701 {
1702     RefPtr<Event> loadEvent(Event::create(eventNames().loadEvent, false, false));
1703     if (m_frame && m_frame->loader()->documentLoader() && !m_frame->loader()->documentLoader()->timing()->loadEventStart()) {
1704         // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching
1705         // the event, so protect it to prevent writing the end time into freed memory.
1706         RefPtr<DocumentLoader> documentLoader = m_frame->loader()->documentLoader();
1707         DocumentLoadTiming* timing = documentLoader->timing();
1708         timing->markLoadEventStart();
1709         dispatchEvent(loadEvent, document());
1710         timing->markLoadEventEnd();
1711     } else
1712         dispatchEvent(loadEvent, document());
1713
1714     // For load events, send a separate load event to the enclosing frame only.
1715     // This is a DOM extension and is independent of bubbling/capturing rules of
1716     // the DOM.
1717     Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
1718     if (ownerElement)
1719         ownerElement->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
1720
1721     InspectorInstrumentation::loadEventFired(frame());
1722 }
1723
1724 bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget)
1725 {
1726     RefPtr<EventTarget> protect = this;
1727     RefPtr<Event> event = prpEvent;
1728
1729     event->setTarget(prpTarget ? prpTarget : this);
1730     event->setCurrentTarget(this);
1731     event->setEventPhase(Event::AT_TARGET);
1732
1733     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this);
1734
1735     bool result = fireEventListeners(event.get());
1736
1737     InspectorInstrumentation::didDispatchEventOnWindow(cookie);
1738
1739     return result;
1740 }
1741
1742 void DOMWindow::removeAllEventListeners()
1743 {
1744     EventTarget::removeAllEventListeners();
1745
1746 #if ENABLE(DEVICE_ORIENTATION)
1747     if (DeviceMotionController* controller = DeviceMotionController::from(page()))
1748         controller->removeAllDeviceEventListeners(this);
1749     if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
1750         controller->removeAllDeviceEventListeners(this);
1751 #endif
1752 #if ENABLE(TOUCH_EVENTS)
1753     if (Document* document = this->document())
1754         document->didRemoveEventTargetNode(document);
1755 #endif
1756
1757 #if ENABLE(PROXIMITY_EVENTS)
1758     if (DeviceProximityController* controller = DeviceProximityController::from(page()))
1759         controller->removeAllDeviceEventListeners(this);
1760 #endif
1761
1762     removeAllUnloadEventListeners(this);
1763     removeAllBeforeUnloadEventListeners(this);
1764 }
1765
1766 void DOMWindow::captureEvents()
1767 {
1768     // Not implemented.
1769 }
1770
1771 void DOMWindow::releaseEvents()
1772 {
1773     // Not implemented.
1774 }
1775
1776 void DOMWindow::finishedLoading()
1777 {
1778     if (m_shouldPrintWhenFinishedLoading) {
1779         m_shouldPrintWhenFinishedLoading = false;
1780         print();
1781     }
1782 }
1783
1784 EventTargetData* DOMWindow::eventTargetData()
1785 {
1786     return &m_eventTargetData;
1787 }
1788
1789 EventTargetData& DOMWindow::ensureEventTargetData()
1790 {
1791     return m_eventTargetData;
1792 }
1793
1794 void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow, SetLocationLocking locking)
1795 {
1796     if (!isCurrentlyDisplayedInFrame())
1797         return;
1798
1799     Document* activeDocument = activeWindow->document();
1800     if (!activeDocument)
1801         return;
1802
1803     if (!activeDocument->canNavigate(m_frame))
1804         return;
1805
1806     Frame* firstFrame = firstWindow->frame();
1807     if (!firstFrame)
1808         return;
1809
1810     KURL completedURL = firstFrame->document()->completeURL(urlString);
1811     if (completedURL.isNull())
1812         return;
1813
1814     if (isInsecureScriptAccess(activeWindow, completedURL))
1815         return;
1816
1817     // We want a new history item if we are processing a user gesture.
1818     m_frame->navigationScheduler()->scheduleLocationChange(activeDocument->securityOrigin(),
1819         // FIXME: What if activeDocument()->frame() is 0?
1820         completedURL, activeDocument->frame()->loader()->outgoingReferrer(),
1821         locking != LockHistoryBasedOnGestureState || !ScriptController::processingUserGesture(),
1822         locking != LockHistoryBasedOnGestureState);
1823 }
1824
1825 void DOMWindow::printErrorMessage(const String& message)
1826 {
1827     if (message.isEmpty())
1828         return;
1829
1830     pageConsole()->addMessage(JSMessageSource, ErrorMessageLevel, message);
1831 }
1832
1833 String DOMWindow::crossDomainAccessErrorMessage(DOMWindow* activeWindow)
1834 {
1835     const KURL& activeWindowURL = activeWindow->document()->url();
1836     if (activeWindowURL.isNull())
1837         return String();
1838
1839     ASSERT(!activeWindow->document()->securityOrigin()->canAccess(document()->securityOrigin()));
1840
1841     // FIXME: This message, and other console messages, have extra newlines. Should remove them.
1842     SecurityOrigin* activeOrigin = activeWindow->document()->securityOrigin();
1843     SecurityOrigin* targetOrigin = document()->securityOrigin();
1844     String message = "Blocked a frame with origin \"" + activeOrigin->toString() + "\" from accessing a frame with origin \"" + targetOrigin->toString() + "\". ";
1845
1846     // Sandbox errors: Use the origin of the frames' location, rather than their actual origin (since we know that at least one will be "null").
1847     KURL activeURL = activeWindow->document()->url();
1848     KURL targetURL = document()->url();
1849     if (document()->isSandboxed(SandboxOrigin) || activeWindow->document()->isSandboxed(SandboxOrigin)) {
1850         message = "Blocked a frame at \"" + SecurityOrigin::create(activeURL)->toString() + "\" from accessing a frame at \"" + SecurityOrigin::create(targetURL)->toString() + "\". ";
1851         if (document()->isSandboxed(SandboxOrigin) && activeWindow->document()->isSandboxed(SandboxOrigin))
1852             return "Sandbox access violation: " + message + " Both frames are sandboxed and lack the \"allow-same-origin\" flag.";
1853         if (document()->isSandboxed(SandboxOrigin))
1854             return "Sandbox access violation: " + message + " The frame being accessed is sandboxed and lacks the \"allow-same-origin\" flag.";
1855         return "Sandbox access violation: " + message + " The frame requesting access is sandboxed and lacks the \"allow-same-origin\" flag.";
1856     }
1857
1858     // 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:'.
1859     if (targetOrigin->protocol() != activeOrigin->protocol())
1860         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";
1861
1862     // 'document.domain' errors.
1863     if (targetOrigin->domainWasSetInDOM() && activeOrigin->domainWasSetInDOM())
1864         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.";
1865     if (activeOrigin->domainWasSetInDOM())
1866         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.";
1867     if (targetOrigin->domainWasSetInDOM())
1868         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.";
1869
1870     // Default.
1871     return message + "Protocols, domains, and ports must match.";
1872 }
1873
1874 bool DOMWindow::isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString)
1875 {
1876     if (!protocolIsJavaScript(urlString))
1877         return false;
1878
1879     // If this DOMWindow isn't currently active in the Frame, then there's no
1880     // way we should allow the access.
1881     // FIXME: Remove this check if we're able to disconnect DOMWindow from
1882     // Frame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054
1883     if (isCurrentlyDisplayedInFrame()) {
1884         // FIXME: Is there some way to eliminate the need for a separate "activeWindow == this" check?
1885         if (activeWindow == this)
1886             return false;
1887
1888         // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script".
1889         // Can we name the SecurityOrigin function better to make this more clear?
1890         if (activeWindow->document()->securityOrigin()->canAccess(document()->securityOrigin()))
1891             return false;
1892     }
1893
1894     printErrorMessage(crossDomainAccessErrorMessage(activeWindow));
1895     return true;
1896 }
1897
1898 PassRefPtr<Frame> DOMWindow::createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures,
1899     DOMWindow* activeWindow, Frame* firstFrame, Frame* openerFrame, PrepareDialogFunction function, void* functionContext)
1900 {
1901     Frame* activeFrame = activeWindow->frame();
1902
1903     KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, emptyString()) : firstFrame->document()->completeURL(urlString);
1904     if (!completedURL.isEmpty() && !completedURL.isValid()) {
1905         // Don't expose client code to invalid URLs.
1906         activeWindow->printErrorMessage("Unable to open a window with invalid URL '" + completedURL.string() + "'.\n");
1907         return 0;
1908     }
1909
1910     // For whatever reason, Firefox uses the first frame to determine the outgoingReferrer. We replicate that behavior here.
1911     String referrer = SecurityPolicy::generateReferrerHeader(firstFrame->document()->referrerPolicy(), completedURL, firstFrame->loader()->outgoingReferrer());
1912
1913     ResourceRequest request(completedURL, referrer);
1914     FrameLoader::addHTTPOriginIfNeeded(request, firstFrame->loader()->outgoingOrigin());
1915     FrameLoadRequest frameRequest(activeWindow->document()->securityOrigin(), request, frameName);
1916
1917     // We pass the opener frame for the lookupFrame in case the active frame is different from
1918     // the opener frame, and the name references a frame relative to the opener frame.
1919     bool created;
1920     RefPtr<Frame> newFrame = WebCore::createWindow(activeFrame, openerFrame, frameRequest, windowFeatures, created);
1921     if (!newFrame)
1922         return 0;
1923
1924     newFrame->loader()->setOpener(openerFrame);
1925     newFrame->page()->setOpenedByDOM();
1926
1927     if (newFrame->document()->domWindow()->isInsecureScriptAccess(activeWindow, completedURL))
1928         return newFrame.release();
1929
1930     if (function)
1931         function(newFrame->document()->domWindow(), functionContext);
1932
1933     if (created)
1934         newFrame->loader()->changeLocation(activeWindow->document()->securityOrigin(), completedURL, referrer, false, false);
1935     else if (!urlString.isEmpty()) {
1936         bool lockHistory = !ScriptController::processingUserGesture();
1937         newFrame->navigationScheduler()->scheduleLocationChange(activeWindow->document()->securityOrigin(), completedURL.string(), referrer, lockHistory, false);
1938     }
1939
1940     // Navigating the new frame could result in it being detached from its page by a navigation policy delegate.
1941     if (!newFrame->page())
1942         return 0;
1943
1944     return newFrame.release();
1945 }
1946
1947 PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
1948     DOMWindow* activeWindow, DOMWindow* firstWindow)
1949 {
1950     if (!isCurrentlyDisplayedInFrame())
1951         return 0;
1952     Document* activeDocument = activeWindow->document();
1953     if (!activeDocument)
1954         return 0;
1955     Frame* firstFrame = firstWindow->frame();
1956     if (!firstFrame)
1957         return 0;
1958
1959     if (!firstWindow->allowPopUp()) {
1960         // Because FrameTree::find() returns true for empty strings, we must check for empty frame names.
1961         // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
1962         if (frameName.isEmpty() || !m_frame->tree()->find(frameName))
1963             return 0;
1964     }
1965
1966     // Get the target frame for the special cases of _top and _parent.
1967     // In those cases, we schedule a location change right now and return early.
1968     Frame* targetFrame = 0;
1969     if (frameName == "_top")
1970         targetFrame = m_frame->tree()->top();
1971     else if (frameName == "_parent") {
1972         if (Frame* parent = m_frame->tree()->parent())
1973             targetFrame = parent;
1974         else
1975             targetFrame = m_frame;
1976     }
1977     if (targetFrame) {
1978         if (!activeDocument->canNavigate(targetFrame))
1979             return 0;
1980
1981         KURL completedURL = firstFrame->document()->completeURL(urlString);
1982
1983         if (targetFrame->document()->domWindow()->isInsecureScriptAccess(activeWindow, completedURL))
1984             return targetFrame->document()->domWindow();
1985
1986         if (urlString.isEmpty())
1987             return targetFrame->document()->domWindow();
1988
1989         // For whatever reason, Firefox uses the first window rather than the active window to
1990         // determine the outgoing referrer. We replicate that behavior here.
1991         bool lockHistory = !ScriptController::processingUserGesture();
1992         targetFrame->navigationScheduler()->scheduleLocationChange(
1993             activeDocument->securityOrigin(),
1994             completedURL,
1995             firstFrame->loader()->outgoingReferrer(),
1996             lockHistory,
1997             false);
1998         return targetFrame->document()->domWindow();
1999     }
2000
2001     WindowFeatures windowFeatures(windowFeaturesString);
2002     RefPtr<Frame> result = createWindow(urlString, frameName, windowFeatures, activeWindow, firstFrame, m_frame);
2003     return result ? result->document()->domWindow() : 0;
2004 }
2005
2006 void DOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString,
2007     DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction function, void* functionContext)
2008 {
2009     if (!isCurrentlyDisplayedInFrame())
2010         return;
2011     Frame* activeFrame = activeWindow->frame();
2012     if (!activeFrame)
2013         return;
2014     Frame* firstFrame = firstWindow->frame();
2015     if (!firstFrame)
2016         return;
2017
2018     // Pages are not allowed to cause modal alerts during BeforeUnload dispatch.
2019     if (page() && page()->isAnyFrameHandlingBeforeUnloadEvent()) {
2020         printErrorMessage("Use of window.showModalDialog is not allowed during beforeunload event dispatch.");
2021         return;
2022     }
2023
2024     if (!canShowModalDialogNow(m_frame) || !firstWindow->allowPopUp())
2025         return;
2026
2027     WindowFeatures windowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view()));
2028     RefPtr<Frame> dialogFrame = createWindow(urlString, emptyAtom, windowFeatures,
2029         activeWindow, firstFrame, m_frame, function, functionContext);
2030     if (!dialogFrame)
2031         return;
2032     dialogFrame->page()->chrome().runModal();
2033 }
2034
2035 void DOMWindow::enableSuddenTermination()
2036 {
2037     if (Page* page = this->page())
2038         page->chrome().enableSuddenTermination();
2039 }
2040
2041 void DOMWindow::disableSuddenTermination()
2042 {
2043     if (Page* page = this->page())
2044         page->chrome().disableSuddenTermination();
2045 }
2046
2047 } // namespace WebCore