OSDN Git Service

am 06295b42: (-s ours) am 4ce956cc: am 3d487c65: Merge "DO NOT MERGE-Move check for...
[android-x86/external-webkit.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 "Base64.h"
34 #include "BeforeUnloadEvent.h"
35 #include "CSSComputedStyleDeclaration.h"
36 #include "CSSRuleList.h"
37 #include "CSSStyleSelector.h"
38 #include "Chrome.h"
39 #include "Console.h"
40 #include "Crypto.h"
41 #include "DOMApplicationCache.h"
42 #include "DOMSelection.h"
43 #include "DOMSettableTokenList.h"
44 #include "DOMStringList.h"
45 #include "DOMTimer.h"
46 #include "DOMTokenList.h"
47 #include "DOMURL.h"
48 #include "Database.h"
49 #include "DatabaseCallback.h"
50 #include "DeviceMotionController.h"
51 #include "DeviceOrientationController.h"
52 #include "Document.h"
53 #include "DocumentLoader.h"
54 #include "Element.h"
55 #include "EventException.h"
56 #include "EventListener.h"
57 #include "EventNames.h"
58 #include "ExceptionCode.h"
59 #include "FloatRect.h"
60 #include "Frame.h"
61 #include "FrameLoadRequest.h"
62 #include "FrameLoader.h"
63 #include "FrameTree.h"
64 #include "FrameView.h"
65 #include "HTMLFrameOwnerElement.h"
66 #include "History.h"
67 #include "IDBFactory.h"
68 #include "IDBFactoryBackendInterface.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 "NotificationCenter.h"
77 #include "Page.h"
78 #include "PageGroup.h"
79 #include "PageTransitionEvent.h"
80 #include "Performance.h"
81 #include "PlatformScreen.h"
82 #include "PlatformString.h"
83 #include "Screen.h"
84 #include "SecurityOrigin.h"
85 #include "SerializedScriptValue.h"
86 #include "Settings.h"
87 #include "Storage.h"
88 #include "StorageArea.h"
89 #include "StorageNamespace.h"
90 #include "StyleMedia.h"
91 #include "SuddenTermination.h"
92 #include "WebKitPoint.h"
93 #include "WindowFeatures.h"
94 #include <algorithm>
95 #include <wtf/CurrentTime.h>
96 #include <wtf/MathExtras.h>
97 #include <wtf/text/StringConcatenate.h>
98
99 #if ENABLE(FILE_SYSTEM)
100 #include "AsyncFileSystem.h"
101 #include "DOMFileSystem.h"
102 #include "ErrorCallback.h"
103 #include "FileError.h"
104 #include "FileSystemCallback.h"
105 #include "FileSystemCallbacks.h"
106 #include "LocalFileSystem.h"
107 #endif
108
109 #if ENABLE(REQUEST_ANIMATION_FRAME)
110 #include "RequestAnimationFrameCallback.h"
111 #endif
112
113 using std::min;
114 using std::max;
115
116 namespace WebCore {
117
118 class PostMessageTimer : public TimerBase {
119 public:
120     PostMessageTimer(DOMWindow* window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin)
121         : m_window(window)
122         , m_message(message)
123         , m_origin(sourceOrigin)
124         , m_source(source)
125         , m_channels(channels)
126         , m_targetOrigin(targetOrigin)
127     {
128     }
129
130     PassRefPtr<MessageEvent> event(ScriptExecutionContext* context)
131     {
132         OwnPtr<MessagePortArray> messagePorts = MessagePort::entanglePorts(*context, m_channels.release());
133         return MessageEvent::create(messagePorts.release(), m_message, m_origin, "", m_source);
134     }
135     SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
136
137 private:
138     virtual void fired()
139     {
140         m_window->postMessageTimerFired(this);
141     }
142
143     RefPtr<DOMWindow> m_window;
144     RefPtr<SerializedScriptValue> m_message;
145     String m_origin;
146     RefPtr<DOMWindow> m_source;
147     OwnPtr<MessagePortChannelArray> m_channels;
148     RefPtr<SecurityOrigin> m_targetOrigin;
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 no smaller than 100 in each dimension and no
313 //    bigger than 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)
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     // Resize the window to between 100 and the screen width and height.
342     window.setWidth(min(max(100.0f, window.width()), screen.width()));
343     window.setHeight(min(max(100.0f, window.height()), screen.height()));
344     
345     // Constrain the window position to the screen.
346     window.setX(max(screen.x(), min(window.x(), screen.maxX() - window.width())));
347     window.setY(max(screen.y(), min(window.y(), screen.maxY() - window.height())));
348 }
349
350 // FIXME: We can remove this function once V8 showModalDialog is changed to use DOMWindow.
351 void DOMWindow::parseModalDialogFeatures(const String& string, HashMap<String, String>& map)
352 {
353     WindowFeatures::parseDialogFeatures(string, map);
354 }
355
356 bool DOMWindow::allowPopUp(Frame* firstFrame)
357 {
358     ASSERT(firstFrame);
359
360     if (ScriptController::processingUserGesture())
361         return true;
362
363     Settings* settings = firstFrame->settings();
364     return settings && settings->javaScriptCanOpenWindowsAutomatically();
365 }
366
367 bool DOMWindow::allowPopUp()
368 {
369     return m_frame && allowPopUp(m_frame);
370 }
371
372 bool DOMWindow::canShowModalDialog(const Frame* frame)
373 {
374     if (!frame)
375         return false;
376     Page* page = frame->page();
377     if (!page)
378         return false;
379     return page->chrome()->canRunModal();
380 }
381
382 bool DOMWindow::canShowModalDialogNow(const Frame* frame)
383 {
384     if (!frame)
385         return false;
386     Page* page = frame->page();
387     if (!page)
388         return false;
389     return page->chrome()->canRunModalNow();
390 }
391
392 DOMWindow::DOMWindow(Frame* frame)
393     : m_shouldPrintWhenFinishedLoading(false)
394     , m_frame(frame)
395 {
396 }
397
398 DOMWindow::~DOMWindow()
399 {
400     if (m_frame)
401         m_frame->clearFormerDOMWindow(this);
402
403     removeAllUnloadEventListeners(this);
404     removeAllBeforeUnloadEventListeners(this);
405 }
406
407 ScriptExecutionContext* DOMWindow::scriptExecutionContext() const
408 {
409     return document();
410 }
411
412 PassRefPtr<MediaQueryList> DOMWindow::matchMedia(const String& media)
413 {
414     return document() ? document()->mediaQueryMatcher()->matchMedia(media) : 0;
415 }
416
417 void DOMWindow::disconnectFrame()
418 {
419     m_frame = 0;
420     clear();
421 }
422
423 void DOMWindow::clear()
424 {
425     if (m_screen)
426         m_screen->disconnectFrame();
427     m_screen = 0;
428
429     if (m_selection)
430         m_selection->disconnectFrame();
431     m_selection = 0;
432
433     if (m_history)
434         m_history->disconnectFrame();
435     m_history = 0;
436
437     m_crypto = 0;
438
439     if (m_locationbar)
440         m_locationbar->disconnectFrame();
441     m_locationbar = 0;
442
443     if (m_menubar)
444         m_menubar->disconnectFrame();
445     m_menubar = 0;
446
447     if (m_personalbar)
448         m_personalbar->disconnectFrame();
449     m_personalbar = 0;
450
451     if (m_scrollbars)
452         m_scrollbars->disconnectFrame();
453     m_scrollbars = 0;
454
455     if (m_statusbar)
456         m_statusbar->disconnectFrame();
457     m_statusbar = 0;
458
459     if (m_toolbar)
460         m_toolbar->disconnectFrame();
461     m_toolbar = 0;
462
463     if (m_console)
464         m_console->disconnectFrame();
465     m_console = 0;
466
467     if (m_navigator)
468         m_navigator->disconnectFrame();
469     m_navigator = 0;
470
471 #if ENABLE(WEB_TIMING)
472     if (m_performance)
473         m_performance->disconnectFrame();
474     m_performance = 0;
475 #endif
476
477     if (m_location)
478         m_location->disconnectFrame();
479     m_location = 0;
480
481     if (m_media)
482         m_media->disconnectFrame();
483     m_media = 0;
484     
485 #if ENABLE(DOM_STORAGE)
486     if (m_sessionStorage)
487         m_sessionStorage->disconnectFrame();
488     m_sessionStorage = 0;
489
490     if (m_localStorage)
491         m_localStorage->disconnectFrame();
492     m_localStorage = 0;
493 #endif
494
495 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
496     if (m_applicationCache)
497         m_applicationCache->disconnectFrame();
498     m_applicationCache = 0;
499 #endif
500
501 #if ENABLE(NOTIFICATIONS)
502     if (m_notifications)
503         m_notifications->disconnectFrame();
504     m_notifications = 0;
505 #endif
506
507 #if ENABLE(INDEXED_DATABASE)
508     m_idbFactory = 0;
509 #endif
510 }
511
512 #if ENABLE(ORIENTATION_EVENTS)
513 int DOMWindow::orientation() const
514 {
515     if (!m_frame)
516         return 0;
517     
518     return m_frame->orientation();
519 }
520 #endif
521
522 Screen* DOMWindow::screen() const
523 {
524     if (!m_screen)
525         m_screen = Screen::create(m_frame);
526     return m_screen.get();
527 }
528
529 History* DOMWindow::history() const
530 {
531     if (!m_history)
532         m_history = History::create(m_frame);
533     return m_history.get();
534 }
535
536 Crypto* DOMWindow::crypto() const
537 {
538     if (!m_crypto)
539         m_crypto = Crypto::create();
540     return m_crypto.get();
541 }
542
543 BarInfo* DOMWindow::locationbar() const
544 {
545     if (!m_locationbar)
546         m_locationbar = BarInfo::create(m_frame, BarInfo::Locationbar);
547     return m_locationbar.get();
548 }
549
550 BarInfo* DOMWindow::menubar() const
551 {
552     if (!m_menubar)
553         m_menubar = BarInfo::create(m_frame, BarInfo::Menubar);
554     return m_menubar.get();
555 }
556
557 BarInfo* DOMWindow::personalbar() const
558 {
559     if (!m_personalbar)
560         m_personalbar = BarInfo::create(m_frame, BarInfo::Personalbar);
561     return m_personalbar.get();
562 }
563
564 BarInfo* DOMWindow::scrollbars() const
565 {
566     if (!m_scrollbars)
567         m_scrollbars = BarInfo::create(m_frame, BarInfo::Scrollbars);
568     return m_scrollbars.get();
569 }
570
571 BarInfo* DOMWindow::statusbar() const
572 {
573     if (!m_statusbar)
574         m_statusbar = BarInfo::create(m_frame, BarInfo::Statusbar);
575     return m_statusbar.get();
576 }
577
578 BarInfo* DOMWindow::toolbar() const
579 {
580     if (!m_toolbar)
581         m_toolbar = BarInfo::create(m_frame, BarInfo::Toolbar);
582     return m_toolbar.get();
583 }
584
585 Console* DOMWindow::console() const
586 {
587     if (!m_console)
588         m_console = Console::create(m_frame);
589     return m_console.get();
590 }
591
592 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
593 DOMApplicationCache* DOMWindow::applicationCache() const
594 {
595     if (!m_applicationCache)
596         m_applicationCache = DOMApplicationCache::create(m_frame);
597     return m_applicationCache.get();
598 }
599 #endif
600
601 Navigator* DOMWindow::navigator() const
602 {
603     if (!m_navigator)
604         m_navigator = Navigator::create(m_frame);
605     return m_navigator.get();
606 }
607
608 #if ENABLE(WEB_TIMING)
609 Performance* DOMWindow::performance() const
610 {
611     if (!m_performance)
612         m_performance = Performance::create(m_frame);
613     return m_performance.get();
614 }
615 #endif
616
617 Location* DOMWindow::location() const
618 {
619     if (!m_location)
620         m_location = Location::create(m_frame);
621     return m_location.get();
622 }
623
624 #if ENABLE(DOM_STORAGE)
625 Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const
626 {
627     if (m_sessionStorage)
628         return m_sessionStorage.get();
629
630     Document* document = this->document();
631     if (!document)
632         return 0;
633
634     if (!document->securityOrigin()->canAccessLocalStorage()) {
635         ec = SECURITY_ERR;
636         return 0;
637     }
638
639     Page* page = document->page();
640     if (!page)
641         return 0;
642
643     RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
644     InspectorInstrumentation::didUseDOMStorage(page, storageArea.get(), false, m_frame);
645
646     m_sessionStorage = Storage::create(m_frame, storageArea.release());
647     return m_sessionStorage.get();
648 }
649
650 Storage* DOMWindow::localStorage(ExceptionCode& ec) const
651 {
652     if (m_localStorage)
653         return m_localStorage.get();
654
655     Document* document = this->document();
656     if (!document)
657         return 0;
658
659     if (!document->securityOrigin()->canAccessLocalStorage()) {
660         ec = SECURITY_ERR;
661         return 0;
662     }
663
664     Page* page = document->page();
665     if (!page)
666         return 0;
667
668     if (!page->settings()->localStorageEnabled())
669         return 0;
670
671     RefPtr<StorageArea> storageArea = page->group().localStorage()->storageArea(document->securityOrigin());
672     InspectorInstrumentation::didUseDOMStorage(page, storageArea.get(), true, m_frame);
673
674     m_localStorage = Storage::create(m_frame, storageArea.release());
675     return m_localStorage.get();
676 }
677 #endif
678
679 #if ENABLE(NOTIFICATIONS)
680 NotificationCenter* DOMWindow::webkitNotifications() const
681 {
682     if (m_notifications)
683         return m_notifications.get();
684
685     Document* document = this->document();
686     if (!document)
687         return 0;
688     
689     Page* page = document->page();
690     if (!page)
691         return 0;
692
693     NotificationPresenter* provider = page->chrome()->notificationPresenter();
694     if (provider) 
695         m_notifications = NotificationCenter::create(document, provider);    
696       
697     return m_notifications.get();
698 }
699 #endif
700
701 void DOMWindow::pageDestroyed()
702 {
703 #if ENABLE(NOTIFICATIONS)
704     // Clearing Notifications requests involves accessing the client so it must be done
705     // before the frame is detached.
706     if (m_notifications)
707         m_notifications->disconnectFrame();
708     m_notifications = 0;
709 #endif
710 }
711
712 #if ENABLE(INDEXED_DATABASE)
713 IDBFactory* DOMWindow::webkitIndexedDB() const
714 {
715     if (m_idbFactory)
716         return m_idbFactory.get();
717
718     Document* document = this->document();
719     if (!document)
720         return 0;
721
722     // FIXME: See if access is allowed.
723
724     Page* page = document->page();
725     if (!page)
726         return 0;
727
728     // FIXME: See if indexedDatabase access is allowed.
729
730     m_idbFactory = IDBFactory::create(page->group().idbFactory());
731     return m_idbFactory.get();
732 }
733 #endif
734
735 #if ENABLE(FILE_SYSTEM)
736 void DOMWindow::requestFileSystem(int type, long long size, PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback)
737 {
738     Document* document = this->document();
739     if (!document)
740         return;
741
742     if (!AsyncFileSystem::isAvailable() || !document->securityOrigin()->canAccessFileSystem()) {
743         DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::SECURITY_ERR));
744         return;
745     }
746
747     AsyncFileSystem::Type fileSystemType = static_cast<AsyncFileSystem::Type>(type);
748     if (fileSystemType != AsyncFileSystem::Temporary && fileSystemType != AsyncFileSystem::Persistent) {
749         DOMFileSystem::scheduleCallback(document, errorCallback, FileError::create(FileError::INVALID_MODIFICATION_ERR));
750         return;
751     }
752
753     LocalFileSystem::localFileSystem().requestFileSystem(document, fileSystemType, size, FileSystemCallbacks::create(successCallback, errorCallback, document), false);
754 }
755
756 COMPILE_ASSERT(static_cast<int>(DOMWindow::TEMPORARY) == static_cast<int>(AsyncFileSystem::Temporary), enum_mismatch);
757 COMPILE_ASSERT(static_cast<int>(DOMWindow::PERSISTENT) == static_cast<int>(AsyncFileSystem::Persistent), enum_mismatch);
758
759 #endif
760
761 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
762 {
763     MessagePortArray ports;
764     if (port)
765         ports.append(port);
766     postMessage(message, &ports, targetOrigin, source, ec);
767 }
768
769 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
770 {
771     if (!m_frame)
772         return;
773
774     // Compute the target origin.  We need to do this synchronously in order
775     // to generate the SYNTAX_ERR exception correctly.
776     RefPtr<SecurityOrigin> target;
777     if (targetOrigin != "*") {
778         target = SecurityOrigin::createFromString(targetOrigin);
779         if (target->isEmpty()) {
780             ec = SYNTAX_ERR;
781             return;
782         }
783     }
784
785     OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec);
786     if (ec)
787         return;
788
789     // Capture the source of the message.  We need to do this synchronously
790     // in order to capture the source of the message correctly.
791     Document* sourceDocument = source->document();
792     if (!sourceDocument)
793         return;
794     String sourceOrigin = sourceDocument->securityOrigin()->toString();
795
796     // Schedule the message.
797     PostMessageTimer* timer = new PostMessageTimer(this, message, sourceOrigin, source, channels.release(), target.get());
798     timer->startOneShot(0);
799 }
800
801 void DOMWindow::postMessageTimerFired(PostMessageTimer* t)
802 {
803     OwnPtr<PostMessageTimer> timer(t);
804
805     if (!document())
806         return;
807
808     if (timer->targetOrigin()) {
809         // Check target origin now since the target document may have changed since the simer was scheduled.
810         if (!timer->targetOrigin()->isSameSchemeHostPort(document()->securityOrigin())) {
811             String message = makeString("Unable to post message to ", timer->targetOrigin()->toString(),
812                                         ". Recipient has origin ", document()->securityOrigin()->toString(), ".\n");
813             console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 0, String());
814             return;
815         }
816     }
817
818     dispatchEvent(timer->event(document()));
819 }
820
821 DOMSelection* DOMWindow::getSelection()
822 {
823     if (!m_selection)
824         m_selection = DOMSelection::create(m_frame);
825     return m_selection.get();
826 }
827
828 Element* DOMWindow::frameElement() const
829 {
830     if (!m_frame)
831         return 0;
832
833     return m_frame->ownerElement();
834 }
835
836 void DOMWindow::focus()
837 {
838     if (!m_frame)
839         return;
840
841     Page* page = m_frame->page();
842     if (!page)
843         return;
844
845     // If we're a top level window, bring the window to the front.
846     if (m_frame == page->mainFrame())
847         page->chrome()->focus();
848
849     if (!m_frame)
850         return;
851
852     m_frame->eventHandler()->focusDocumentView();
853 }
854
855 void DOMWindow::blur()
856 {
857     if (!m_frame)
858         return;
859
860     Page* page = m_frame->page();
861     if (!page)
862         return;
863
864     if (m_frame != page->mainFrame())
865         return;
866
867     page->chrome()->unfocus();
868 }
869
870 void DOMWindow::close(ScriptExecutionContext* context)
871 {
872     if (!m_frame)
873         return;
874
875     Page* page = m_frame->page();
876     if (!page)
877         return;
878
879     if (m_frame != page->mainFrame())
880         return;
881
882     if (context) {
883         ASSERT(WTF::isMainThread());
884         Frame* activeFrame = static_cast<Document*>(context)->frame();
885         if (!activeFrame)
886             return;
887
888         if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
889             return;
890     }
891
892     Settings* settings = m_frame->settings();
893     bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows();
894
895     if (!(page->openedByDOM() || page->backForward()->count() <= 1 || allowScriptsToCloseWindows))
896         return;
897
898     if (!m_frame->loader()->shouldClose())
899         return;
900
901     page->chrome()->closeWindowSoon();
902 }
903
904 void DOMWindow::print()
905 {
906     if (!m_frame)
907         return;
908
909     Page* page = m_frame->page();
910     if (!page)
911         return;
912
913     if (m_frame->loader()->activeDocumentLoader()->isLoading()) {
914         m_shouldPrintWhenFinishedLoading = true;
915         return;
916     }
917     m_shouldPrintWhenFinishedLoading = false;
918     page->chrome()->print(m_frame);
919 }
920
921 void DOMWindow::stop()
922 {
923     if (!m_frame)
924         return;
925
926     // We must check whether the load is complete asynchronously, because we might still be parsing
927     // the document until the callstack unwinds.
928     m_frame->loader()->stopForUserCancel(true);
929 }
930
931 void DOMWindow::alert(const String& message)
932 {
933     if (!m_frame)
934         return;
935
936     m_frame->document()->updateStyleIfNeeded();
937
938     Page* page = m_frame->page();
939     if (!page)
940         return;
941
942     page->chrome()->runJavaScriptAlert(m_frame, message);
943 }
944
945 bool DOMWindow::confirm(const String& message)
946 {
947     if (!m_frame)
948         return false;
949
950     m_frame->document()->updateStyleIfNeeded();
951
952     Page* page = m_frame->page();
953     if (!page)
954         return false;
955
956     return page->chrome()->runJavaScriptConfirm(m_frame, message);
957 }
958
959 String DOMWindow::prompt(const String& message, const String& defaultValue)
960 {
961     if (!m_frame)
962         return String();
963
964     m_frame->document()->updateStyleIfNeeded();
965
966     Page* page = m_frame->page();
967     if (!page)
968         return String();
969
970     String returnValue;
971     if (page->chrome()->runJavaScriptPrompt(m_frame, message, defaultValue, returnValue))
972         return returnValue;
973
974     return String();
975 }
976
977 String DOMWindow::btoa(const String& stringToEncode, ExceptionCode& ec)
978 {
979     if (stringToEncode.isNull())
980         return String();
981
982     if (!stringToEncode.containsOnlyLatin1()) {
983         ec = INVALID_CHARACTER_ERR;
984         return String();
985     }
986
987     return base64Encode(stringToEncode.latin1());
988 }
989
990 String DOMWindow::atob(const String& encodedString, ExceptionCode& ec)
991 {
992     if (encodedString.isNull())
993         return String();
994
995     if (!encodedString.containsOnlyLatin1()) {
996         ec = INVALID_CHARACTER_ERR;
997         return String();
998     }
999
1000     Vector<char> out;
1001     if (!base64Decode(encodedString, out, FailOnInvalidCharacter)) {
1002         ec = INVALID_CHARACTER_ERR;
1003         return String();
1004     }
1005
1006     return String(out.data(), out.size());
1007 }
1008
1009 bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const
1010 {
1011     if (!m_frame)
1012         return false;
1013
1014     // FIXME (13016): Support wholeWord, searchInFrames and showDialog
1015     return m_frame->editor()->findString(string, !backwards, caseSensitive, wrap, false);
1016 }
1017
1018 bool DOMWindow::offscreenBuffering() const
1019 {
1020     return true;
1021 }
1022
1023 int DOMWindow::outerHeight() const
1024 {
1025     if (!m_frame)
1026         return 0;
1027
1028     Page* page = m_frame->page();
1029     if (!page)
1030         return 0;
1031
1032     return static_cast<int>(page->chrome()->windowRect().height());
1033 }
1034
1035 int DOMWindow::outerWidth() const
1036 {
1037     if (!m_frame)
1038         return 0;
1039
1040     Page* page = m_frame->page();
1041     if (!page)
1042         return 0;
1043
1044     return static_cast<int>(page->chrome()->windowRect().width());
1045 }
1046
1047 int DOMWindow::innerHeight() const
1048 {
1049     if (!m_frame)
1050         return 0;
1051
1052     FrameView* view = m_frame->view();
1053     if (!view)
1054         return 0;
1055     
1056 #if PLATFORM(ANDROID)
1057     return static_cast<int>(view->actualHeight() / m_frame->pageZoomFactor());
1058 #else
1059     return static_cast<int>(view->height() / m_frame->pageZoomFactor());
1060 #endif
1061 }
1062
1063 int DOMWindow::innerWidth() const
1064 {
1065     if (!m_frame)
1066         return 0;
1067
1068     FrameView* view = m_frame->view();
1069     if (!view)
1070         return 0;
1071
1072 #if PLATFORM(ANDROID)
1073     return static_cast<int>(view->actualWidth() / m_frame->pageZoomFactor());
1074 #else
1075     return static_cast<int>(view->width() / m_frame->pageZoomFactor());
1076 #endif
1077 }
1078
1079 int DOMWindow::screenX() const
1080 {
1081     if (!m_frame)
1082         return 0;
1083
1084     Page* page = m_frame->page();
1085     if (!page)
1086         return 0;
1087
1088     return static_cast<int>(page->chrome()->windowRect().x());
1089 }
1090
1091 int DOMWindow::screenY() const
1092 {
1093     if (!m_frame)
1094         return 0;
1095
1096     Page* page = m_frame->page();
1097     if (!page)
1098         return 0;
1099
1100     return static_cast<int>(page->chrome()->windowRect().y());
1101 }
1102
1103 int DOMWindow::scrollX() const
1104 {
1105     if (!m_frame)
1106         return 0;
1107
1108     FrameView* view = m_frame->view();
1109     if (!view)
1110         return 0;
1111
1112     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1113
1114 #if PLATFORM(ANDROID)
1115     return static_cast<int>(view->actualScrollX() / m_frame->pageZoomFactor());
1116 #else
1117     return static_cast<int>(view->scrollX() / m_frame->pageZoomFactor());
1118 #endif
1119 }
1120
1121 int DOMWindow::scrollY() const
1122 {
1123     if (!m_frame)
1124         return 0;
1125
1126     FrameView* view = m_frame->view();
1127     if (!view)
1128         return 0;
1129
1130     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1131
1132 #if PLATFORM(ANDROID)
1133     return static_cast<int>(view->actualScrollY() / m_frame->pageZoomFactor());
1134 #else
1135     return static_cast<int>(view->scrollY() / m_frame->pageZoomFactor());
1136 #endif
1137 }
1138
1139 bool DOMWindow::closed() const
1140 {
1141     return !m_frame;
1142 }
1143
1144 unsigned DOMWindow::length() const
1145 {
1146     if (!m_frame)
1147         return 0;
1148
1149     return m_frame->tree()->childCount();
1150 }
1151
1152 String DOMWindow::name() const
1153 {
1154     if (!m_frame)
1155         return String();
1156
1157     return m_frame->tree()->name();
1158 }
1159
1160 void DOMWindow::setName(const String& string)
1161 {
1162     if (!m_frame)
1163         return;
1164
1165     m_frame->tree()->setName(string);
1166 }
1167
1168 void DOMWindow::setStatus(const String& string) 
1169 {
1170     m_status = string;
1171
1172     if (!m_frame)
1173         return;
1174
1175     Page* page = m_frame->page();
1176     if (!page)
1177         return;
1178
1179     ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1180     page->chrome()->setStatusbarText(m_frame, m_status);
1181
1182     
1183 void DOMWindow::setDefaultStatus(const String& string) 
1184 {
1185     m_defaultStatus = string;
1186
1187     if (!m_frame)
1188         return;
1189
1190     Page* page = m_frame->page();
1191     if (!page)
1192         return;
1193
1194     ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1195     page->chrome()->setStatusbarText(m_frame, m_defaultStatus);
1196 }
1197
1198 DOMWindow* DOMWindow::self() const
1199 {
1200     if (!m_frame)
1201         return 0;
1202
1203     return m_frame->domWindow();
1204 }
1205
1206 DOMWindow* DOMWindow::opener() const
1207 {
1208     if (!m_frame)
1209         return 0;
1210
1211     Frame* opener = m_frame->loader()->opener();
1212     if (!opener)
1213         return 0;
1214
1215     return opener->domWindow();
1216 }
1217
1218 DOMWindow* DOMWindow::parent() const
1219 {
1220     if (!m_frame)
1221         return 0;
1222
1223     Frame* parent = m_frame->tree()->parent(true);
1224     if (parent)
1225         return parent->domWindow();
1226
1227     return m_frame->domWindow();
1228 }
1229
1230 DOMWindow* DOMWindow::top() const
1231 {
1232     if (!m_frame)
1233         return 0;
1234
1235     Page* page = m_frame->page();
1236     if (!page)
1237         return 0;
1238
1239     return m_frame->tree()->top(true)->domWindow();
1240 }
1241
1242 Document* DOMWindow::document() const
1243 {
1244     // FIXME: This function shouldn't need a frame to work.
1245     if (!m_frame)
1246         return 0;
1247
1248     // The m_frame pointer is not zeroed out when the window is put into b/f cache, so it can hold an unrelated document/window pair.
1249     // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content.
1250     if (m_frame->domWindow() != this)
1251         return 0;
1252
1253     ASSERT(m_frame->document());
1254     return m_frame->document();
1255 }
1256
1257 PassRefPtr<StyleMedia> DOMWindow::styleMedia() const
1258 {
1259     if (!m_media)
1260         m_media = StyleMedia::create(m_frame);
1261     return m_media.get();
1262 }
1263
1264 PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const
1265 {
1266     if (!elt)
1267         return 0;
1268
1269     return computedStyle(elt, false, pseudoElt);
1270 }
1271
1272 PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* elt, const String&, bool authorOnly) const
1273 {
1274     if (!m_frame)
1275         return 0;
1276
1277     Settings* settings = m_frame->settings();
1278     return m_frame->document()->styleSelector()->styleRulesForElement(elt, authorOnly, false, settings && settings->crossOriginCheckInGetMatchedCSSRulesDisabled() ? AllCSSRules : SameOriginCSSRulesOnly);
1279 }
1280
1281 PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const
1282 {
1283     if (!node || !p)
1284         return 0;
1285
1286     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1287
1288     FloatPoint pagePoint(p->x(), p->y());
1289     pagePoint = node->convertToPage(pagePoint);
1290     return WebKitPoint::create(pagePoint.x(), pagePoint.y());
1291 }
1292
1293 PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const
1294 {
1295     if (!node || !p)
1296         return 0;
1297
1298     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1299
1300     FloatPoint nodePoint(p->x(), p->y());
1301     nodePoint = node->convertFromPage(nodePoint);
1302     return WebKitPoint::create(nodePoint.x(), nodePoint.y());
1303 }
1304
1305 double DOMWindow::devicePixelRatio() const
1306 {
1307     if (!m_frame)
1308         return 0.0;
1309
1310     Page* page = m_frame->page();
1311     if (!page)
1312         return 0.0;
1313
1314     return page->chrome()->scaleFactor();
1315 }
1316
1317 #if ENABLE(DATABASE)
1318 PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec)
1319 {
1320     RefPtr<Database> database = 0;
1321     if (m_frame && AbstractDatabase::isAvailable() && m_frame->document()->securityOrigin()->canAccessDatabase())
1322         database = Database::openDatabase(m_frame->document(), name, version, displayName, estimatedSize, creationCallback, ec);
1323
1324     if (!database && !ec)
1325         ec = SECURITY_ERR;
1326
1327     return database;
1328 }
1329 #endif
1330
1331 void DOMWindow::scrollBy(int x, int y) const
1332 {
1333     if (!m_frame)
1334         return;
1335
1336     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1337
1338     RefPtr<FrameView> view = m_frame->view();
1339     if (!view)
1340         return;
1341
1342     view->scrollBy(IntSize(x, y));
1343 }
1344
1345 void DOMWindow::scrollTo(int x, int y) const
1346 {
1347     if (!m_frame)
1348         return;
1349
1350     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1351
1352     RefPtr<FrameView> view = m_frame->view();
1353     if (!view)
1354         return;
1355
1356     int zoomedX = static_cast<int>(x * m_frame->pageZoomFactor());
1357     int zoomedY = static_cast<int>(y * m_frame->pageZoomFactor());
1358     view->setScrollPosition(IntPoint(zoomedX, zoomedY));
1359 }
1360
1361 void DOMWindow::moveBy(float x, float y) const
1362 {
1363     if (!m_frame)
1364         return;
1365
1366     Page* page = m_frame->page();
1367     if (!page)
1368         return;
1369
1370     if (m_frame != page->mainFrame())
1371         return;
1372
1373     FloatRect fr = page->chrome()->windowRect();
1374     FloatRect update = fr;
1375     update.move(x, y);
1376     // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1377     adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
1378     page->chrome()->setWindowRect(fr);
1379 }
1380
1381 void DOMWindow::moveTo(float x, float y) const
1382 {
1383     if (!m_frame)
1384         return;
1385
1386     Page* page = m_frame->page();
1387     if (!page)
1388         return;
1389
1390     if (m_frame != page->mainFrame())
1391         return;
1392
1393     FloatRect fr = page->chrome()->windowRect();
1394     FloatRect sr = screenAvailableRect(page->mainFrame()->view());
1395     fr.setLocation(sr.location());
1396     FloatRect update = fr;
1397     update.move(x, y);     
1398     // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1399     adjustWindowRect(sr, fr, update);
1400     page->chrome()->setWindowRect(fr);
1401 }
1402
1403 void DOMWindow::resizeBy(float x, float y) const
1404 {
1405     if (!m_frame)
1406         return;
1407
1408     Page* page = m_frame->page();
1409     if (!page)
1410         return;
1411
1412     if (m_frame != page->mainFrame())
1413         return;
1414
1415     FloatRect fr = page->chrome()->windowRect();
1416     FloatSize dest = fr.size() + FloatSize(x, y);
1417     FloatRect update(fr.location(), dest);
1418     adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
1419     page->chrome()->setWindowRect(fr);
1420 }
1421
1422 void DOMWindow::resizeTo(float width, float height) const
1423 {
1424     if (!m_frame)
1425         return;
1426
1427     Page* page = m_frame->page();
1428     if (!page)
1429         return;
1430
1431     if (m_frame != page->mainFrame())
1432         return;
1433
1434     FloatRect fr = page->chrome()->windowRect();
1435     FloatSize dest = FloatSize(width, height);
1436     FloatRect update(fr.location(), dest);
1437     adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
1438     page->chrome()->setWindowRect(fr);
1439 }
1440
1441 int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
1442 {
1443     ScriptExecutionContext* context = scriptExecutionContext();
1444     if (!context) {
1445         ec = INVALID_ACCESS_ERR;
1446         return -1;
1447     }
1448     return DOMTimer::install(context, action, timeout, true);
1449 }
1450
1451 void DOMWindow::clearTimeout(int timeoutId)
1452 {
1453     ScriptExecutionContext* context = scriptExecutionContext();
1454     if (!context)
1455         return;
1456     DOMTimer::removeById(context, timeoutId);
1457 }
1458
1459 int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
1460 {
1461     ScriptExecutionContext* context = scriptExecutionContext();
1462     if (!context) {
1463         ec = INVALID_ACCESS_ERR;
1464         return -1;
1465     }
1466     return DOMTimer::install(context, action, timeout, false);
1467 }
1468
1469 void DOMWindow::clearInterval(int timeoutId)
1470 {
1471     ScriptExecutionContext* context = scriptExecutionContext();
1472     if (!context)
1473         return;
1474     DOMTimer::removeById(context, timeoutId);
1475 }
1476
1477 #if ENABLE(REQUEST_ANIMATION_FRAME)
1478 int DOMWindow::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback, Element* e)
1479 {
1480     if (Document* d = document())
1481         return d->webkitRequestAnimationFrame(callback, e);
1482     return 0;
1483 }
1484
1485 void DOMWindow::webkitCancelRequestAnimationFrame(int id)
1486 {
1487     if (Document* d = document())
1488         d->webkitCancelRequestAnimationFrame(id);
1489 }
1490 #endif
1491
1492 bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1493 {
1494     if (!EventTarget::addEventListener(eventType, listener, useCapture))
1495         return false;
1496
1497     if (Document* document = this->document())
1498         document->addListenerTypeIfNeeded(eventType);
1499
1500     if (eventType == eventNames().unloadEvent)
1501         addUnloadEventListener(this);
1502     else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
1503         addBeforeUnloadEventListener(this);
1504 #if ENABLE(DEVICE_ORIENTATION)
1505     else if (eventType == eventNames().devicemotionEvent && frame() && frame()->page() && frame()->page()->deviceMotionController())
1506         frame()->page()->deviceMotionController()->addListener(this);
1507     else if (eventType == eventNames().deviceorientationEvent && frame() && frame()->page() && frame()->page()->deviceOrientationController())
1508         frame()->page()->deviceOrientationController()->addListener(this);
1509 #endif
1510
1511     return true;
1512 }
1513
1514 bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
1515 {
1516     if (!EventTarget::removeEventListener(eventType, listener, useCapture))
1517         return false;
1518
1519     if (eventType == eventNames().unloadEvent)
1520         removeUnloadEventListener(this);
1521     else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
1522         removeBeforeUnloadEventListener(this);
1523 #if ENABLE(DEVICE_ORIENTATION)
1524     else if (eventType == eventNames().devicemotionEvent && frame() && frame()->page() && frame()->page()->deviceMotionController())
1525         frame()->page()->deviceMotionController()->removeListener(this);
1526     else if (eventType == eventNames().deviceorientationEvent && frame() && frame()->page() && frame()->page()->deviceOrientationController())
1527         frame()->page()->deviceOrientationController()->removeListener(this);
1528 #endif
1529
1530     return true;
1531 }
1532
1533 void DOMWindow::dispatchLoadEvent()
1534 {
1535     RefPtr<Event> loadEvent(Event::create(eventNames().loadEvent, false, false));
1536     // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching
1537     // the event, so protect it to prevent writing the end time into freed memory.
1538     if (RefPtr<DocumentLoader> documentLoader = m_frame ? m_frame->loader()->documentLoader() : 0) {
1539         DocumentLoadTiming* timing = documentLoader->timing();
1540         dispatchTimedEvent(loadEvent, document(), &timing->loadEventStart, &timing->loadEventEnd);
1541     } else
1542         dispatchEvent(loadEvent, document());
1543
1544     // For load events, send a separate load event to the enclosing frame only.
1545     // This is a DOM extension and is independent of bubbling/capturing rules of
1546     // the DOM.
1547     Element* ownerElement = document()->ownerElement();
1548     if (ownerElement) {
1549         RefPtr<Event> ownerEvent = Event::create(eventNames().loadEvent, false, false);
1550         ownerEvent->setTarget(ownerElement);
1551         ownerElement->dispatchGenericEvent(ownerEvent.release());
1552     }
1553
1554     InspectorInstrumentation::loadEventFired(frame(), url());
1555 }
1556
1557 bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget)
1558 {
1559     RefPtr<EventTarget> protect = this;
1560     RefPtr<Event> event = prpEvent;
1561
1562     event->setTarget(prpTarget ? prpTarget : this);
1563     event->setCurrentTarget(this);
1564     event->setEventPhase(Event::AT_TARGET);
1565
1566     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this);
1567
1568     bool result = fireEventListeners(event.get());
1569
1570     InspectorInstrumentation::didDispatchEventOnWindow(cookie);
1571
1572     return result;
1573 }
1574
1575 void DOMWindow::dispatchTimedEvent(PassRefPtr<Event> event, Document* target, double* startTime, double* endTime)
1576 {
1577     ASSERT(startTime);
1578     ASSERT(endTime);
1579     *startTime = currentTime();
1580     dispatchEvent(event, target);
1581     *endTime = currentTime();
1582 }
1583
1584 void DOMWindow::removeAllEventListeners()
1585 {
1586     EventTarget::removeAllEventListeners();
1587
1588 #if ENABLE(DEVICE_ORIENTATION)
1589     if (frame() && frame()->page() && frame()->page()->deviceMotionController())
1590         frame()->page()->deviceMotionController()->removeAllListeners(this);
1591     if (frame() && frame()->page() && frame()->page()->deviceOrientationController())
1592         frame()->page()->deviceOrientationController()->removeAllListeners(this);
1593 #endif
1594
1595     removeAllUnloadEventListeners(this);
1596     removeAllBeforeUnloadEventListeners(this);
1597 }
1598
1599 void DOMWindow::captureEvents()
1600 {
1601     // Not implemented.
1602 }
1603
1604 void DOMWindow::releaseEvents()
1605 {
1606     // Not implemented.
1607 }
1608
1609 void DOMWindow::finishedLoading()
1610 {
1611     if (m_shouldPrintWhenFinishedLoading) {
1612         m_shouldPrintWhenFinishedLoading = false;
1613         print();
1614     }
1615 }
1616
1617 EventTargetData* DOMWindow::eventTargetData()
1618 {
1619     return &m_eventTargetData;
1620 }
1621
1622 EventTargetData* DOMWindow::ensureEventTargetData()
1623 {
1624     return &m_eventTargetData;
1625 }
1626
1627 #if ENABLE(DOM_STORAGE) && defined(ANDROID)
1628 void DOMWindow::clearDOMStorage()
1629 {
1630     if (m_sessionStorage)
1631         m_sessionStorage->disconnectFrame();
1632     m_sessionStorage = 0;
1633
1634     if (m_localStorage)
1635         m_localStorage->disconnectFrame();
1636     m_localStorage = 0;
1637 }
1638 #endif
1639
1640 void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow, SetLocationLocking locking)
1641 {
1642     if (!m_frame)
1643         return;
1644
1645     Frame* activeFrame = activeWindow->frame();
1646     if (!activeFrame)
1647         return;
1648
1649     if (!activeFrame->loader()->shouldAllowNavigation(m_frame))
1650         return;
1651
1652     Frame* firstFrame = firstWindow->frame();
1653     if (!firstFrame)
1654         return;
1655
1656     KURL completedURL = firstFrame->document()->completeURL(urlString);
1657     if (completedURL.isNull())
1658         return;
1659
1660     if (isInsecureScriptAccess(activeWindow, urlString))
1661         return;
1662
1663     // We want a new history item if we are processing a user gesture.
1664     m_frame->navigationScheduler()->scheduleLocationChange(activeFrame->document()->securityOrigin(),
1665         completedURL, activeFrame->loader()->outgoingReferrer(),
1666         locking != LockHistoryBasedOnGestureState || !activeFrame->script()->anyPageIsProcessingUserGesture(),
1667         locking != LockHistoryBasedOnGestureState);
1668 }
1669
1670 void DOMWindow::printErrorMessage(const String& message)
1671 {
1672     if (message.isEmpty())
1673         return;
1674
1675     Settings* settings = m_frame->settings();
1676     if (!settings)
1677         return;
1678     if (settings->privateBrowsingEnabled())
1679         return;
1680
1681     // FIXME: Add arguments so that we can provide a correct source URL and line number.
1682     console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
1683 }
1684
1685 String DOMWindow::crossDomainAccessErrorMessage(DOMWindow* activeWindow)
1686 {
1687     const KURL& activeWindowURL = activeWindow->url();
1688     if (activeWindowURL.isNull())
1689         return String();
1690
1691     // FIXME: This error message should contain more specifics of why the same origin check has failed.
1692     // Perhaps we should involve the security origin object in composing it.
1693     // FIXME: This message, and other console messages, have extra newlines. Should remove them.
1694     return makeString("Unsafe JavaScript attempt to access frame with URL ", m_url.string(),
1695         " from frame with URL ", activeWindowURL.string(), ". Domains, protocols and ports must match.\n");
1696 }
1697
1698 bool DOMWindow::isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString)
1699 {
1700     if (!protocolIsJavaScript(urlString))
1701         return false;
1702
1703     // FIXME: Is there some way to eliminate the need for a separate "activeWindow == this" check?
1704     if (activeWindow == this)
1705         return false;
1706
1707     // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script".
1708     // Can we name the SecurityOrigin function better to make this more clear?
1709     if (activeWindow->securityOrigin()->canAccess(securityOrigin()))
1710         return false;
1711
1712     printErrorMessage(crossDomainAccessErrorMessage(activeWindow));
1713     return true;
1714 }
1715
1716 Frame* DOMWindow::createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures,
1717     DOMWindow* activeWindow, Frame* firstFrame, Frame* openerFrame, PrepareDialogFunction function, void* functionContext)
1718 {
1719     Frame* activeFrame = activeWindow->frame();
1720
1721     // For whatever reason, Firefox uses the first frame to determine the outgoingReferrer. We replicate that behavior here.
1722     String referrer = firstFrame->loader()->outgoingReferrer();
1723
1724     KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, "") : firstFrame->document()->completeURL(urlString);
1725     ResourceRequest request(completedURL, referrer);
1726     FrameLoader::addHTTPOriginIfNeeded(request, firstFrame->loader()->outgoingOrigin());
1727     FrameLoadRequest frameRequest(activeWindow->securityOrigin(), request, frameName);
1728
1729     // We pass the opener frame for the lookupFrame in case the active frame is different from
1730     // the opener frame, and the name references a frame relative to the opener frame.
1731     bool created;
1732     Frame* newFrame = WebCore::createWindow(activeFrame, openerFrame, frameRequest, windowFeatures, created);
1733     if (!newFrame)
1734         return 0;
1735
1736     newFrame->loader()->setOpener(openerFrame);
1737     newFrame->page()->setOpenedByDOM();
1738
1739     if (newFrame->domWindow()->isInsecureScriptAccess(activeWindow, urlString))
1740         return newFrame;
1741
1742     if (function)
1743         function(newFrame->domWindow(), functionContext);
1744
1745     if (created)
1746         newFrame->loader()->changeLocation(activeWindow->securityOrigin(), completedURL, referrer, false, false);
1747     else if (!urlString.isEmpty()) {
1748         newFrame->navigationScheduler()->scheduleLocationChange(activeWindow->securityOrigin(), completedURL.string(), referrer,
1749             !activeFrame->script()->anyPageIsProcessingUserGesture(), false);
1750     }
1751
1752     return newFrame;
1753 }
1754
1755 PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
1756     DOMWindow* activeWindow, DOMWindow* firstWindow)
1757 {
1758     if (!m_frame)
1759         return 0;
1760     Frame* activeFrame = activeWindow->frame();
1761     if (!activeFrame)
1762         return 0;
1763     Frame* firstFrame = firstWindow->frame();
1764     if (!firstFrame)
1765         return 0;
1766
1767     if (!firstWindow->allowPopUp()) {
1768         // Because FrameTree::find() returns true for empty strings, we must check for empty frame names.
1769         // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
1770         if (frameName.isEmpty() || !m_frame->tree()->find(frameName))
1771             return 0;
1772     }
1773
1774     // Get the target frame for the special cases of _top and _parent.
1775     // In those cases, we schedule a location change right now and return early.
1776     Frame* targetFrame = 0;
1777     if (frameName == "_top")
1778         targetFrame = m_frame->tree()->top();
1779     else if (frameName == "_parent") {
1780         if (Frame* parent = m_frame->tree()->parent())
1781             targetFrame = parent;
1782         else
1783             targetFrame = m_frame;
1784     }
1785     if (targetFrame) {
1786         if (!activeFrame->loader()->shouldAllowNavigation(targetFrame))
1787             return 0;
1788
1789         if (isInsecureScriptAccess(activeWindow, urlString))
1790             return targetFrame->domWindow();
1791
1792         if (urlString.isEmpty())
1793             return targetFrame->domWindow();
1794
1795         // For whatever reason, Firefox uses the first window rather than the active window to
1796         // determine the outgoing referrer. We replicate that behavior here.
1797         targetFrame->navigationScheduler()->scheduleLocationChange(activeFrame->document()->securityOrigin(),
1798             firstFrame->document()->completeURL(urlString).string(),
1799             firstFrame->loader()->outgoingReferrer(),
1800             !activeFrame->script()->anyPageIsProcessingUserGesture(), false);
1801
1802         return targetFrame->domWindow();
1803     }
1804
1805     WindowFeatures windowFeatures(windowFeaturesString);
1806     FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
1807         windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
1808     Page* page = m_frame->page();
1809     DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
1810     windowFeatures.x = windowRect.x();
1811     windowFeatures.y = windowRect.y();
1812     windowFeatures.height = windowRect.height();
1813     windowFeatures.width = windowRect.width();
1814
1815     Frame* result = createWindow(urlString, frameName, windowFeatures, activeWindow, firstFrame, m_frame);
1816     return result ? result->domWindow() : 0;
1817 }
1818
1819 void DOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString,
1820     DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction function, void* functionContext)
1821 {
1822     if (!m_frame)
1823         return;
1824     Frame* activeFrame = activeWindow->frame();
1825     if (!activeFrame)
1826         return;
1827     Frame* firstFrame = firstWindow->frame();
1828     if (!firstFrame)
1829         return;
1830
1831     if (!canShowModalDialogNow(m_frame) || !firstWindow->allowPopUp())
1832         return;
1833
1834     Frame* dialogFrame = createWindow(urlString, emptyAtom, WindowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())),
1835         activeWindow, firstFrame, m_frame, function, functionContext);
1836     if (!dialogFrame)
1837         return;
1838
1839     dialogFrame->page()->chrome()->runModal();
1840 }
1841
1842 #if ENABLE(BLOB)
1843 DOMURL* DOMWindow::webkitURL() const
1844 {
1845     if (!m_domURL)
1846         m_domURL = DOMURL::create(this->scriptExecutionContext());
1847     return m_domURL.get();
1848 }
1849 #endif
1850
1851 } // namespace WebCore