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