2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "DOMWindow.h"
30 #include "AbstractDatabase.h"
31 #include "BackForwardController.h"
33 #include "BeforeUnloadEvent.h"
34 #include "CSSComputedStyleDeclaration.h"
35 #include "CSSRuleList.h"
39 #include "DOMApplicationCache.h"
40 #include "DOMSelection.h"
41 #include "DOMSettableTokenList.h"
42 #include "DOMStringList.h"
44 #include "DOMTokenList.h"
46 #include "DOMWindowExtension.h"
47 #include "DOMWindowNotifications.h"
49 #include "DatabaseCallback.h"
50 #include "DeviceMotionController.h"
51 #include "DeviceOrientationController.h"
53 #include "DocumentLoader.h"
55 #include "EventException.h"
56 #include "EventListener.h"
57 #include "EventNames.h"
58 #include "ExceptionCode.h"
59 #include "FloatRect.h"
61 #include "FrameLoadRequest.h"
62 #include "FrameLoader.h"
63 #include "FrameLoaderClient.h"
64 #include "FrameTree.h"
65 #include "FrameView.h"
66 #include "HTMLFrameOwnerElement.h"
68 #include "InspectorInstrumentation.h"
71 #include "MediaQueryList.h"
72 #include "MediaQueryMatcher.h"
73 #include "MessageEvent.h"
74 #include "Navigator.h"
76 #include "PageGroup.h"
77 #include "PageTransitionEvent.h"
78 #include "Performance.h"
79 #include "PlatformScreen.h"
80 #include "RuntimeEnabledFeatures.h"
81 #include "ScheduledAction.h"
83 #include "ScriptCallStack.h"
84 #include "ScriptCallStackFactory.h"
85 #include "SecurityOrigin.h"
86 #include "SerializedScriptValue.h"
89 #include "StorageArea.h"
90 #include "StorageNamespace.h"
91 #include "StyleMedia.h"
92 #include "StyleResolver.h"
93 #include "SuddenTermination.h"
94 #include "WebKitPoint.h"
95 #include "WindowFeatures.h"
96 #include "WindowFocusAllowedIndicator.h"
98 #include <wtf/CurrentTime.h>
99 #include <wtf/MainThread.h>
100 #include <wtf/MathExtras.h>
101 #include <wtf/text/Base64.h>
102 #include <wtf/text/WTFString.h>
104 #if ENABLE(REQUEST_ANIMATION_FRAME)
105 #include "RequestAnimationFrameCallback.h"
108 #if ENABLE(TIZEN_SEARCH_PROVIDER)
109 #include "External.h"
117 class PostMessageTimer : public TimerBase {
119 PostMessageTimer(DOMWindow* window, PassRefPtr<SerializedScriptValue> message, const String& sourceOrigin, PassRefPtr<DOMWindow> source, PassOwnPtr<MessagePortChannelArray> channels, SecurityOrigin* targetOrigin, PassRefPtr<ScriptCallStack> stackTrace)
122 , m_origin(sourceOrigin)
124 , m_channels(channels)
125 , m_targetOrigin(targetOrigin)
126 , m_stackTrace(stackTrace)
130 PassRefPtr<MessageEvent> event(ScriptExecutionContext* context)
132 OwnPtr<MessagePortArray> messagePorts = MessagePort::entanglePorts(*context, m_channels.release());
133 return MessageEvent::create(messagePorts.release(), m_message, m_origin, "", m_source);
135 SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); }
136 ScriptCallStack* stackTrace() const { return m_stackTrace.get(); }
141 m_window->postMessageTimerFired(adoptPtr(this));
142 // This object is deleted now.
145 RefPtr<DOMWindow> m_window;
146 RefPtr<SerializedScriptValue> m_message;
148 RefPtr<DOMWindow> m_source;
149 OwnPtr<MessagePortChannelArray> m_channels;
150 RefPtr<SecurityOrigin> m_targetOrigin;
151 RefPtr<ScriptCallStack> m_stackTrace;
154 typedef HashCountedSet<DOMWindow*> DOMWindowSet;
156 static DOMWindowSet& windowsWithUnloadEventListeners()
158 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithUnloadEventListeners, ());
159 return windowsWithUnloadEventListeners;
162 static DOMWindowSet& windowsWithBeforeUnloadEventListeners()
164 DEFINE_STATIC_LOCAL(DOMWindowSet, windowsWithBeforeUnloadEventListeners, ());
165 return windowsWithBeforeUnloadEventListeners;
168 static void addUnloadEventListener(DOMWindow* domWindow)
170 DOMWindowSet& set = windowsWithUnloadEventListeners();
172 disableSuddenTermination();
176 static void removeUnloadEventListener(DOMWindow* domWindow)
178 DOMWindowSet& set = windowsWithUnloadEventListeners();
179 DOMWindowSet::iterator it = set.find(domWindow);
184 enableSuddenTermination();
187 static void removeAllUnloadEventListeners(DOMWindow* domWindow)
189 DOMWindowSet& set = windowsWithUnloadEventListeners();
190 DOMWindowSet::iterator it = set.find(domWindow);
195 enableSuddenTermination();
198 static void addBeforeUnloadEventListener(DOMWindow* domWindow)
200 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
202 disableSuddenTermination();
206 static void removeBeforeUnloadEventListener(DOMWindow* domWindow)
208 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
209 DOMWindowSet::iterator it = set.find(domWindow);
214 enableSuddenTermination();
217 static void removeAllBeforeUnloadEventListeners(DOMWindow* domWindow)
219 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
220 DOMWindowSet::iterator it = set.find(domWindow);
225 enableSuddenTermination();
228 static bool allowsBeforeUnloadListeners(DOMWindow* window)
230 ASSERT_ARG(window, window);
231 Frame* frame = window->frame();
234 Page* page = frame->page();
237 return frame == page->mainFrame();
240 bool DOMWindow::dispatchAllPendingBeforeUnloadEvents()
242 DOMWindowSet& set = windowsWithBeforeUnloadEventListeners();
246 static bool alreadyDispatched = false;
247 ASSERT(!alreadyDispatched);
248 if (alreadyDispatched)
251 Vector<RefPtr<DOMWindow> > windows;
252 DOMWindowSet::iterator end = set.end();
253 for (DOMWindowSet::iterator it = set.begin(); it != end; ++it)
254 windows.append(it->first);
256 size_t size = windows.size();
257 for (size_t i = 0; i < size; ++i) {
258 DOMWindow* window = windows[i].get();
259 if (!set.contains(window))
262 Frame* frame = window->frame();
266 if (!frame->loader()->shouldClose())
270 enableSuddenTermination();
272 alreadyDispatched = true;
277 unsigned DOMWindow::pendingUnloadEventListeners() const
279 return windowsWithUnloadEventListeners().count(const_cast<DOMWindow*>(this));
282 void DOMWindow::dispatchAllPendingUnloadEvents()
284 DOMWindowSet& set = windowsWithUnloadEventListeners();
288 static bool alreadyDispatched = false;
289 ASSERT(!alreadyDispatched);
290 if (alreadyDispatched)
293 Vector<RefPtr<DOMWindow> > windows;
294 DOMWindowSet::iterator end = set.end();
295 for (DOMWindowSet::iterator it = set.begin(); it != end; ++it)
296 windows.append(it->first);
298 size_t size = windows.size();
299 for (size_t i = 0; i < size; ++i) {
300 DOMWindow* window = windows[i].get();
301 if (!set.contains(window))
304 window->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), window->document());
305 window->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), window->document());
308 enableSuddenTermination();
310 alreadyDispatched = true;
314 // 1) Validates the pending changes are not changing to NaN
315 // 2) Constrains the window rect to no smaller than 100 in each dimension and no
316 // bigger than the the float rect's dimensions.
317 // 3) Constrain window rect to within the top and left boundaries of the screen rect
318 // 4) Constraint the window rect to within the bottom and right boundaries of the
320 // 5) Translate the window rect coordinates to be within the coordinate space of
322 void DOMWindow::adjustWindowRect(const FloatRect& screen, FloatRect& window, const FloatRect& pendingChanges)
324 // Make sure we're in a valid state before adjusting dimensions.
325 ASSERT(isfinite(screen.x()));
326 ASSERT(isfinite(screen.y()));
327 ASSERT(isfinite(screen.width()));
328 ASSERT(isfinite(screen.height()));
329 ASSERT(isfinite(window.x()));
330 ASSERT(isfinite(window.y()));
331 ASSERT(isfinite(window.width()));
332 ASSERT(isfinite(window.height()));
334 // Update window values if new requested values are not NaN.
335 if (!isnan(pendingChanges.x()))
336 window.setX(pendingChanges.x());
337 if (!isnan(pendingChanges.y()))
338 window.setY(pendingChanges.y());
339 if (!isnan(pendingChanges.width()))
340 window.setWidth(pendingChanges.width());
341 if (!isnan(pendingChanges.height()))
342 window.setHeight(pendingChanges.height());
344 // Resize the window to between 100 and the screen width and height.
345 window.setWidth(min(max(100.0f, window.width()), screen.width()));
346 window.setHeight(min(max(100.0f, window.height()), screen.height()));
348 // Constrain the window position to the screen.
349 window.setX(max(screen.x(), min(window.x(), screen.maxX() - window.width())));
350 window.setY(max(screen.y(), min(window.y(), screen.maxY() - window.height())));
353 // FIXME: We can remove this function once V8 showModalDialog is changed to use DOMWindow.
354 void DOMWindow::parseModalDialogFeatures(const String& string, HashMap<String, String>& map)
356 WindowFeatures::parseDialogFeatures(string, map);
359 bool DOMWindow::allowPopUp(Frame* firstFrame)
363 if (ScriptController::processingUserGesture())
366 Settings* settings = firstFrame->settings();
367 return settings && settings->javaScriptCanOpenWindowsAutomatically();
370 bool DOMWindow::allowPopUp()
372 return m_frame && allowPopUp(m_frame);
375 bool DOMWindow::canShowModalDialog(const Frame* frame)
379 Page* page = frame->page();
382 return page->chrome()->canRunModal();
385 bool DOMWindow::canShowModalDialogNow(const Frame* frame)
389 Page* page = frame->page();
392 return page->chrome()->canRunModalNow();
395 DOMWindow::DOMWindow(Frame* frame)
396 : FrameDestructionObserver(frame)
397 , m_shouldPrintWhenFinishedLoading(false)
398 , m_suspendedForPageCache(false)
402 DOMWindow::~DOMWindow()
405 if (!m_suspendedForPageCache) {
409 ASSERT(!m_locationbar);
411 ASSERT(!m_personalbar);
412 ASSERT(!m_scrollbars);
413 ASSERT(!m_statusbar);
416 ASSERT(!m_navigator);
417 #if ENABLE(WEB_TIMING)
418 ASSERT(!m_performance);
422 ASSERT(!m_sessionStorage);
423 ASSERT(!m_localStorage);
424 ASSERT(!m_applicationCache);
430 #if ENABLE(TIZEN_SEARCH_PROVIDER)
434 if (m_suspendedForPageCache)
435 willDestroyCachedFrame();
437 willDestroyDocumentInFrame();
439 // As the ASSERTs above indicate, this clear should only be necesary if this DOMWindow is suspended for the page cache.
440 // But we don't want to risk any of these objects hanging around after we've been destroyed.
441 clearDOMWindowProperties();
443 removeAllUnloadEventListeners(this);
444 removeAllBeforeUnloadEventListeners(this);
447 const AtomicString& DOMWindow::interfaceName() const
449 return eventNames().interfaceForDOMWindow;
452 ScriptExecutionContext* DOMWindow::scriptExecutionContext() const
457 DOMWindow* DOMWindow::toDOMWindow()
462 PassRefPtr<MediaQueryList> DOMWindow::matchMedia(const String& media)
464 return document() ? document()->mediaQueryMatcher()->matchMedia(media) : 0;
467 void DOMWindow::setSecurityOrigin(SecurityOrigin* securityOrigin)
469 m_securityOrigin = securityOrigin;
472 Page* DOMWindow::page()
474 return frame() ? frame()->page() : 0;
477 void DOMWindow::frameDestroyed()
479 willDestroyDocumentInFrame();
480 FrameDestructionObserver::frameDestroyed();
481 clearDOMWindowProperties();
484 void DOMWindow::willDetachPage()
486 InspectorInstrumentation::frameWindowDiscarded(m_frame, this);
489 void DOMWindow::willDestroyCachedFrame()
491 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
492 // unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInCachedFrame.
493 Vector<DOMWindowProperty*> properties;
494 copyToVector(m_properties, properties);
495 for (size_t i = 0; i < properties.size(); ++i)
496 properties[i]->willDestroyGlobalObjectInCachedFrame();
499 void DOMWindow::willDestroyDocumentInFrame()
501 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
502 // unregister themselves from the DOMWindow as a result of the call to willDestroyGlobalObjectInFrame.
503 Vector<DOMWindowProperty*> properties;
504 copyToVector(m_properties, properties);
505 for (size_t i = 0; i < properties.size(); ++i)
506 properties[i]->willDestroyGlobalObjectInFrame();
509 void DOMWindow::willDetachDocumentFromFrame()
511 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
512 // unregister themselves from the DOMWindow as a result of the call to willDetachGlobalObjectFromFrame.
513 Vector<DOMWindowProperty*> properties;
514 copyToVector(m_properties, properties);
515 for (size_t i = 0; i < properties.size(); ++i)
516 properties[i]->willDetachGlobalObjectFromFrame();
519 void DOMWindow::registerProperty(DOMWindowProperty* property)
521 m_properties.add(property);
524 void DOMWindow::unregisterProperty(DOMWindowProperty* property)
526 m_properties.remove(property);
529 void DOMWindow::clear()
531 // The main frame will always try to clear its DOMWindow when a new load is committed, even if that
532 // DOMWindow is suspended in the page cache.
533 // In those cases we need to make sure we don't actually clear it.
534 if (m_suspendedForPageCache)
537 willDestroyDocumentInFrame();
538 clearDOMWindowProperties();
541 void DOMWindow::suspendForPageCache()
543 disconnectDOMWindowProperties();
544 m_suspendedForPageCache = true;
547 void DOMWindow::resumeFromPageCache()
549 reconnectDOMWindowProperties();
550 m_suspendedForPageCache = false;
553 void DOMWindow::disconnectDOMWindowProperties()
555 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
556 // unregister themselves from the DOMWindow as a result of the call to disconnectFrameForPageCache.
557 Vector<DOMWindowProperty*> properties;
558 copyToVector(m_properties, properties);
559 for (size_t i = 0; i < properties.size(); ++i)
560 properties[i]->disconnectFrameForPageCache();
563 void DOMWindow::reconnectDOMWindowProperties()
565 ASSERT(m_suspendedForPageCache);
566 // It is necessary to copy m_properties to a separate vector because the DOMWindowProperties may
567 // unregister themselves from the DOMWindow as a result of the call to reconnectFromPageCache.
568 Vector<DOMWindowProperty*> properties;
569 copyToVector(m_properties, properties);
570 for (size_t i = 0; i < properties.size(); ++i)
571 properties[i]->reconnectFrameFromPageCache(m_frame);
574 void DOMWindow::clearDOMWindowProperties()
576 m_properties.clear();
589 #if ENABLE(WEB_TIMING)
594 m_sessionStorage = 0;
596 m_applicationCache = 0;
600 #if ENABLE(TIZEN_SEARCH_PROVIDER)
605 bool DOMWindow::isCurrentlyDisplayedInFrame() const
607 return m_frame && m_frame->domWindow() == this;
610 #if ENABLE(ORIENTATION_EVENTS)
611 int DOMWindow::orientation() const
616 return m_frame->orientation();
620 Screen* DOMWindow::screen() const
622 if (!isCurrentlyDisplayedInFrame())
625 m_screen = Screen::create(m_frame);
626 return m_screen.get();
629 History* DOMWindow::history() const
631 if (!isCurrentlyDisplayedInFrame())
634 m_history = History::create(m_frame);
635 return m_history.get();
638 Crypto* DOMWindow::crypto() const
640 if (!isCurrentlyDisplayedInFrame())
643 m_crypto = Crypto::create();
644 return m_crypto.get();
647 BarInfo* DOMWindow::locationbar() const
649 if (!isCurrentlyDisplayedInFrame())
652 m_locationbar = BarInfo::create(m_frame, BarInfo::Locationbar);
653 return m_locationbar.get();
656 BarInfo* DOMWindow::menubar() const
658 if (!isCurrentlyDisplayedInFrame())
661 m_menubar = BarInfo::create(m_frame, BarInfo::Menubar);
662 return m_menubar.get();
665 BarInfo* DOMWindow::personalbar() const
667 if (!isCurrentlyDisplayedInFrame())
670 m_personalbar = BarInfo::create(m_frame, BarInfo::Personalbar);
671 return m_personalbar.get();
674 BarInfo* DOMWindow::scrollbars() const
676 if (!isCurrentlyDisplayedInFrame())
679 m_scrollbars = BarInfo::create(m_frame, BarInfo::Scrollbars);
680 return m_scrollbars.get();
683 BarInfo* DOMWindow::statusbar() const
685 if (!isCurrentlyDisplayedInFrame())
688 m_statusbar = BarInfo::create(m_frame, BarInfo::Statusbar);
689 return m_statusbar.get();
692 BarInfo* DOMWindow::toolbar() const
694 if (!isCurrentlyDisplayedInFrame())
697 m_toolbar = BarInfo::create(m_frame, BarInfo::Toolbar);
698 return m_toolbar.get();
701 Console* DOMWindow::console() const
703 if (!isCurrentlyDisplayedInFrame())
706 m_console = Console::create(m_frame);
707 return m_console.get();
710 DOMApplicationCache* DOMWindow::applicationCache() const
712 if (!isCurrentlyDisplayedInFrame())
714 if (!m_applicationCache)
715 m_applicationCache = DOMApplicationCache::create(m_frame);
716 return m_applicationCache.get();
719 Navigator* DOMWindow::navigator() const
721 if (!isCurrentlyDisplayedInFrame())
724 m_navigator = Navigator::create(m_frame);
725 return m_navigator.get();
728 #if ENABLE(WEB_TIMING)
729 Performance* DOMWindow::performance() const
731 if (!isCurrentlyDisplayedInFrame())
734 m_performance = Performance::create(m_frame);
735 return m_performance.get();
739 Location* DOMWindow::location() const
741 if (!isCurrentlyDisplayedInFrame())
744 m_location = Location::create(m_frame);
745 return m_location.get();
748 Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const
750 if (!isCurrentlyDisplayedInFrame())
752 if (m_sessionStorage)
753 return m_sessionStorage.get();
755 Document* document = this->document();
759 if (!document->securityOrigin()->canAccessLocalStorage()) {
764 Page* page = document->page();
768 RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(document->securityOrigin());
769 InspectorInstrumentation::didUseDOMStorage(page, storageArea.get(), false, m_frame);
771 m_sessionStorage = Storage::create(m_frame, storageArea.release());
772 return m_sessionStorage.get();
775 Storage* DOMWindow::localStorage(ExceptionCode& ec) const
777 if (!isCurrentlyDisplayedInFrame())
780 return m_localStorage.get();
782 Document* document = this->document();
786 if (!document->securityOrigin()->canAccessLocalStorage()) {
791 Page* page = document->page();
795 if (!page->settings()->localStorageEnabled())
798 RefPtr<StorageArea> storageArea = page->group().localStorage()->storageArea(document->securityOrigin());
799 InspectorInstrumentation::didUseDOMStorage(page, storageArea.get(), true, m_frame);
801 m_localStorage = Storage::create(m_frame, storageArea.release());
802 return m_localStorage.get();
805 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, MessagePort* port, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
807 MessagePortArray ports;
810 postMessage(message, &ports, targetOrigin, source, ec);
813 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec)
815 if (!isCurrentlyDisplayedInFrame())
818 Document* sourceDocument = source->document();
820 // Compute the target origin. We need to do this synchronously in order
821 // to generate the SYNTAX_ERR exception correctly.
822 RefPtr<SecurityOrigin> target;
823 if (targetOrigin == "/") {
826 target = sourceDocument->securityOrigin();
827 } else if (targetOrigin != "*") {
828 target = SecurityOrigin::createFromString(targetOrigin);
829 // It doesn't make sense target a postMessage at a unique origin
830 // because there's no way to represent a unique origin in a string.
831 if (target->isUnique()) {
837 OwnPtr<MessagePortChannelArray> channels = MessagePort::disentanglePorts(ports, ec);
841 // Capture the source of the message. We need to do this synchronously
842 // in order to capture the source of the message correctly.
845 String sourceOrigin = sourceDocument->securityOrigin()->toString();
847 // Capture stack trace only when inspector front-end is loaded as it may be time consuming.
848 RefPtr<ScriptCallStack> stackTrace;
849 if (InspectorInstrumentation::hasFrontends())
850 stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
852 // Schedule the message.
853 PostMessageTimer* timer = new PostMessageTimer(this, message, sourceOrigin, source, channels.release(), target.get(), stackTrace.release());
854 timer->startOneShot(0);
857 void DOMWindow::postMessageTimerFired(PassOwnPtr<PostMessageTimer> t)
859 OwnPtr<PostMessageTimer> timer(t);
861 if (!document() || !isCurrentlyDisplayedInFrame())
864 RefPtr<MessageEvent> event = timer->event(document());
866 // Give the embedder a chance to intercept this postMessage because this
867 // DOMWindow might be a proxy for another in browsers that support
868 // postMessage calls across WebKit instances.
869 if (m_frame->loader()->client()->willCheckAndDispatchMessageEvent(timer->targetOrigin(), event.get()))
872 dispatchMessageEventWithOriginCheck(timer->targetOrigin(), event, timer->stackTrace());
875 void DOMWindow::dispatchMessageEventWithOriginCheck(SecurityOrigin* intendedTargetOrigin, PassRefPtr<Event> event, PassRefPtr<ScriptCallStack> stackTrace)
877 if (intendedTargetOrigin) {
878 // Check target origin now since the target document may have changed since the timer was scheduled.
879 if (!intendedTargetOrigin->isSameSchemeHostPort(document()->securityOrigin())) {
880 String message = "Unable to post message to " + intendedTargetOrigin->toString() +
881 ". Recipient has origin " + document()->securityOrigin()->toString() + ".\n";
882 console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, stackTrace);
887 dispatchEvent(event);
890 DOMSelection* DOMWindow::getSelection()
892 if (!isCurrentlyDisplayedInFrame() || !m_frame)
895 return m_frame->document()->getSelection();
898 Element* DOMWindow::frameElement() const
903 return m_frame->ownerElement();
906 void DOMWindow::focus(ScriptExecutionContext* context)
911 Page* page = m_frame->page();
915 bool allowFocus = WindowFocusAllowedIndicator::windowFocusAllowed() || !m_frame->settings()->windowFocusRestricted();
917 ASSERT(isMainThread());
918 Document* activeDocument = static_cast<Document*>(context);
919 if (opener() && activeDocument->domWindow() == opener())
923 // If we're a top level window, bring the window to the front.
924 if (m_frame == page->mainFrame() && allowFocus)
925 page->chrome()->focus();
930 m_frame->eventHandler()->focusDocumentView();
933 void DOMWindow::blur()
939 Page* page = m_frame->page();
943 if (m_frame->settings()->windowFocusRestricted())
946 if (m_frame != page->mainFrame())
949 page->chrome()->unfocus();
952 void DOMWindow::close(ScriptExecutionContext* context)
957 Page* page = m_frame->page();
961 if (m_frame != page->mainFrame())
965 ASSERT(isMainThread());
966 Document* activeDocument = static_cast<Document*>(context);
970 if (!activeDocument->canNavigate(m_frame))
974 Settings* settings = m_frame->settings();
975 bool allowScriptsToCloseWindows = settings && settings->allowScriptsToCloseWindows();
977 if (!(page->openedByDOM() || page->backForward()->count() <= 1 || allowScriptsToCloseWindows))
980 if (!m_frame->loader()->shouldClose())
983 page->chrome()->closeWindowSoon();
986 void DOMWindow::print()
991 Page* page = m_frame->page();
995 if (m_frame->loader()->activeDocumentLoader()->isLoading()) {
996 m_shouldPrintWhenFinishedLoading = true;
999 m_shouldPrintWhenFinishedLoading = false;
1000 page->chrome()->print(m_frame);
1003 void DOMWindow::stop()
1008 // We must check whether the load is complete asynchronously, because we might still be parsing
1009 // the document until the callstack unwinds.
1010 m_frame->loader()->stopForUserCancel(true);
1013 void DOMWindow::alert(const String& message)
1018 m_frame->document()->updateStyleIfNeeded();
1020 Page* page = m_frame->page();
1024 page->chrome()->runJavaScriptAlert(m_frame, message);
1027 bool DOMWindow::confirm(const String& message)
1032 m_frame->document()->updateStyleIfNeeded();
1034 Page* page = m_frame->page();
1038 return page->chrome()->runJavaScriptConfirm(m_frame, message);
1041 String DOMWindow::prompt(const String& message, const String& defaultValue)
1046 m_frame->document()->updateStyleIfNeeded();
1048 Page* page = m_frame->page();
1053 if (page->chrome()->runJavaScriptPrompt(m_frame, message, defaultValue, returnValue))
1059 String DOMWindow::btoa(const String& stringToEncode, ExceptionCode& ec)
1061 if (stringToEncode.isNull())
1064 if (!stringToEncode.containsOnlyLatin1()) {
1065 ec = INVALID_CHARACTER_ERR;
1069 return base64Encode(stringToEncode.latin1());
1072 String DOMWindow::atob(const String& encodedString, ExceptionCode& ec)
1074 if (encodedString.isNull())
1077 if (!encodedString.containsOnlyLatin1()) {
1078 ec = INVALID_CHARACTER_ERR;
1083 if (!base64Decode(encodedString, out, Base64FailOnInvalidCharacter)) {
1084 ec = INVALID_CHARACTER_ERR;
1088 return String(out.data(), out.size());
1091 bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const
1093 if (!isCurrentlyDisplayedInFrame())
1096 // FIXME (13016): Support wholeWord, searchInFrames and showDialog
1097 return m_frame->editor()->findString(string, !backwards, caseSensitive, wrap, false);
1100 bool DOMWindow::offscreenBuffering() const
1105 int DOMWindow::outerHeight() const
1110 Page* page = m_frame->page();
1113 return static_cast<int>(page->chrome()->windowRect().height());
1116 int DOMWindow::outerWidth() const
1121 Page* page = m_frame->page();
1124 return static_cast<int>(page->chrome()->windowRect().width());
1127 int DOMWindow::innerHeight() const
1132 FrameView* view = m_frame->view();
1136 // If the device height is overridden, do not include the horizontal scrollbar into the innerHeight (since it is absent on the real device).
1137 bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenHeightOverride(m_frame);
1138 return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRect(includeScrollbars).height()));
1141 int DOMWindow::innerWidth() const
1146 FrameView* view = m_frame->view();
1150 // If the device width is overridden, do not include the vertical scrollbar into the innerWidth (since it is absent on the real device).
1151 bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(m_frame);
1152 return view->mapFromLayoutToCSSUnits(static_cast<int>(view->visibleContentRect(includeScrollbars).width()));
1155 int DOMWindow::screenX() const
1160 Page* page = m_frame->page();
1164 return static_cast<int>(page->chrome()->windowRect().x());
1167 int DOMWindow::screenY() const
1172 Page* page = m_frame->page();
1176 return static_cast<int>(page->chrome()->windowRect().y());
1179 int DOMWindow::scrollX() const
1184 FrameView* view = m_frame->view();
1188 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1190 return view->mapFromLayoutToCSSUnits(view->scrollX());
1193 int DOMWindow::scrollY() const
1198 FrameView* view = m_frame->view();
1202 m_frame->document()->updateLayoutIgnorePendingStylesheets();
1204 return view->mapFromLayoutToCSSUnits(view->scrollY());
1207 bool DOMWindow::closed() const
1212 unsigned DOMWindow::length() const
1214 if (!isCurrentlyDisplayedInFrame())
1217 return m_frame->tree()->scopedChildCount();
1220 String DOMWindow::name() const
1225 return m_frame->tree()->name();
1228 void DOMWindow::setName(const String& string)
1233 m_frame->tree()->setName(string);
1236 void DOMWindow::setStatus(const String& string)
1243 Page* page = m_frame->page();
1247 ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1248 page->chrome()->setStatusbarText(m_frame, m_status);
1251 void DOMWindow::setDefaultStatus(const String& string)
1253 m_defaultStatus = string;
1258 Page* page = m_frame->page();
1262 ASSERT(m_frame->document()); // Client calls shouldn't be made when the frame is in inconsistent state.
1263 page->chrome()->setStatusbarText(m_frame, m_defaultStatus);
1266 DOMWindow* DOMWindow::self() const
1271 return m_frame->domWindow();
1274 DOMWindow* DOMWindow::opener() const
1279 Frame* opener = m_frame->loader()->opener();
1283 return opener->domWindow();
1286 DOMWindow* DOMWindow::parent() const
1291 Frame* parent = m_frame->tree()->parent();
1293 return parent->domWindow();
1295 return m_frame->domWindow();
1298 DOMWindow* DOMWindow::top() const
1303 Page* page = m_frame->page();
1307 return m_frame->tree()->top()->domWindow();
1310 Document* DOMWindow::document() const
1312 if (!isCurrentlyDisplayedInFrame())
1315 // FIXME: This function shouldn't need a frame to work.
1316 ASSERT(m_frame->document());
1317 return m_frame->document();
1320 PassRefPtr<StyleMedia> DOMWindow::styleMedia() const
1322 if (!isCurrentlyDisplayedInFrame())
1325 m_media = StyleMedia::create(m_frame);
1326 return m_media.get();
1329 PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const String& pseudoElt) const
1334 return CSSComputedStyleDeclaration::create(elt, false, pseudoElt);
1337 PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const String& pseudoElement, bool authorOnly) const
1339 if (!isCurrentlyDisplayedInFrame())
1342 unsigned colonStart = pseudoElement[0] == ':' ? (pseudoElement[1] == ':' ? 2 : 1) : 0;
1343 CSSSelector::PseudoType pseudoType = CSSSelector::parsePseudoType(AtomicString(pseudoElement.substring(colonStart)));
1344 if (pseudoType == CSSSelector::PseudoUnknown && !pseudoElement.isEmpty())
1347 unsigned rulesToInclude = StyleResolver::AuthorCSSRules;
1349 rulesToInclude |= StyleResolver::UAAndUserCSSRules;
1350 if (Settings* settings = m_frame->settings()) {
1351 if (settings->crossOriginCheckInGetMatchedCSSRulesDisabled())
1352 rulesToInclude |= StyleResolver::CrossOriginCSSRules;
1355 PseudoId pseudoId = CSSSelector::pseudoId(pseudoType);
1357 return m_frame->document()->styleResolver()->pseudoStyleRulesForElement(element, pseudoId, rulesToInclude);
1360 PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromNodeToPage(Node* node, const WebKitPoint* p) const
1368 document()->updateLayoutIgnorePendingStylesheets();
1370 FloatPoint pagePoint(p->x(), p->y());
1371 pagePoint = node->convertToPage(pagePoint);
1372 return WebKitPoint::create(pagePoint.x(), pagePoint.y());
1375 PassRefPtr<WebKitPoint> DOMWindow::webkitConvertPointFromPageToNode(Node* node, const WebKitPoint* p) const
1383 document()->updateLayoutIgnorePendingStylesheets();
1385 FloatPoint nodePoint(p->x(), p->y());
1386 nodePoint = node->convertFromPage(nodePoint);
1387 return WebKitPoint::create(nodePoint.x(), nodePoint.y());
1390 double DOMWindow::devicePixelRatio() const
1395 Page* page = m_frame->page();
1399 return page->deviceScaleFactor();
1402 void DOMWindow::scrollBy(int x, int y) const
1404 if (!isCurrentlyDisplayedInFrame())
1407 document()->updateLayoutIgnorePendingStylesheets();
1409 FrameView* view = m_frame->view();
1413 IntSize scaledOffset(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
1414 view->scrollBy(scaledOffset);
1417 void DOMWindow::scrollTo(int x, int y) const
1419 if (!isCurrentlyDisplayedInFrame())
1422 document()->updateLayoutIgnorePendingStylesheets();
1424 RefPtr<FrameView> view = m_frame->view();
1428 IntPoint layoutPos(view->mapFromCSSToLayoutUnits(x), view->mapFromCSSToLayoutUnits(y));
1429 view->setScrollPosition(layoutPos);
1432 void DOMWindow::moveBy(float x, float y) const
1437 Page* page = m_frame->page();
1441 if (m_frame != page->mainFrame())
1444 FloatRect fr = page->chrome()->windowRect();
1445 FloatRect update = fr;
1447 // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1448 adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
1449 page->chrome()->setWindowRect(fr);
1452 void DOMWindow::moveTo(float x, float y) const
1457 Page* page = m_frame->page();
1461 if (m_frame != page->mainFrame())
1464 FloatRect fr = page->chrome()->windowRect();
1465 FloatRect sr = screenAvailableRect(page->mainFrame()->view());
1466 fr.setLocation(sr.location());
1467 FloatRect update = fr;
1469 // Security check (the spec talks about UniversalBrowserWrite to disable this check...)
1470 adjustWindowRect(sr, fr, update);
1471 page->chrome()->setWindowRect(fr);
1474 void DOMWindow::resizeBy(float x, float y) const
1479 Page* page = m_frame->page();
1483 if (m_frame != page->mainFrame())
1486 FloatRect fr = page->chrome()->windowRect();
1487 FloatSize dest = fr.size() + FloatSize(x, y);
1488 FloatRect update(fr.location(), dest);
1489 adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
1490 page->chrome()->setWindowRect(fr);
1493 void DOMWindow::resizeTo(float width, float height) const
1498 Page* page = m_frame->page();
1502 if (m_frame != page->mainFrame())
1505 FloatRect fr = page->chrome()->windowRect();
1506 FloatSize dest = FloatSize(width, height);
1507 FloatRect update(fr.location(), dest);
1508 adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update);
1509 page->chrome()->setWindowRect(fr);
1512 int DOMWindow::setTimeout(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
1514 ScriptExecutionContext* context = scriptExecutionContext();
1516 ec = INVALID_ACCESS_ERR;
1519 return DOMTimer::install(context, action, timeout, true);
1522 void DOMWindow::clearTimeout(int timeoutId)
1524 ScriptExecutionContext* context = scriptExecutionContext();
1527 DOMTimer::removeById(context, timeoutId);
1530 int DOMWindow::setInterval(PassOwnPtr<ScheduledAction> action, int timeout, ExceptionCode& ec)
1532 ScriptExecutionContext* context = scriptExecutionContext();
1534 ec = INVALID_ACCESS_ERR;
1537 return DOMTimer::install(context, action, timeout, false);
1540 void DOMWindow::clearInterval(int timeoutId)
1542 ScriptExecutionContext* context = scriptExecutionContext();
1545 DOMTimer::removeById(context, timeoutId);
1548 #if ENABLE(REQUEST_ANIMATION_FRAME)
1549 int DOMWindow::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback)
1551 if (Document* d = document())
1552 return d->webkitRequestAnimationFrame(callback);
1556 void DOMWindow::webkitCancelAnimationFrame(int id)
1558 if (Document* d = document())
1559 d->webkitCancelAnimationFrame(id);
1563 static void didAddStorageEventListener(DOMWindow* window)
1565 // Creating these WebCore::Storage objects informs the system that we'd like to receive
1566 // notifications about storage events that might be triggered in other processes. Rather
1567 // than subscribe to these notifications explicitly, we subscribe to them implicitly to
1568 // simplify the work done by the system.
1569 ExceptionCode unused;
1570 window->localStorage(unused);
1571 window->sessionStorage(unused);
1574 bool DOMWindow::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
1576 if (!EventTarget::addEventListener(eventType, listener, useCapture))
1579 if (Document* document = this->document()) {
1580 document->addListenerTypeIfNeeded(eventType);
1581 if (eventType == eventNames().mousewheelEvent)
1582 document->didAddWheelEventHandler();
1583 else if (eventNames().isTouchEventType(eventType))
1584 document->didAddTouchEventHandler();
1585 else if (eventType == eventNames().storageEvent)
1586 didAddStorageEventListener(this);
1589 if (eventType == eventNames().unloadEvent)
1590 addUnloadEventListener(this);
1591 else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
1592 addBeforeUnloadEventListener(this);
1593 #if ENABLE(DEVICE_ORIENTATION)
1594 else if (eventType == eventNames().devicemotionEvent) {
1595 if (DeviceMotionController* controller = DeviceMotionController::from(page()))
1596 controller->addListener(this);
1597 } else if (eventType == eventNames().deviceorientationEvent) {
1598 if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
1599 controller->addListener(this);
1606 bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
1608 if (!EventTarget::removeEventListener(eventType, listener, useCapture))
1611 if (Document* document = this->document()) {
1612 if (eventType == eventNames().mousewheelEvent)
1613 document->didRemoveWheelEventHandler();
1614 else if (eventNames().isTouchEventType(eventType))
1615 document->didRemoveTouchEventHandler();
1618 if (eventType == eventNames().unloadEvent)
1619 removeUnloadEventListener(this);
1620 else if (eventType == eventNames().beforeunloadEvent && allowsBeforeUnloadListeners(this))
1621 removeBeforeUnloadEventListener(this);
1622 #if ENABLE(DEVICE_ORIENTATION)
1623 else if (eventType == eventNames().devicemotionEvent) {
1624 if (DeviceMotionController* controller = DeviceMotionController::from(page()))
1625 controller->removeListener(this);
1626 } else if (eventType == eventNames().deviceorientationEvent) {
1627 if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
1628 controller->removeListener(this);
1635 void DOMWindow::dispatchLoadEvent()
1637 RefPtr<Event> loadEvent(Event::create(eventNames().loadEvent, false, false));
1638 if (m_frame && m_frame->loader()->documentLoader() && !m_frame->loader()->documentLoader()->timing()->loadEventStart()) {
1639 // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed while dispatching
1640 // the event, so protect it to prevent writing the end time into freed memory.
1641 RefPtr<DocumentLoader> documentLoader = m_frame->loader()->documentLoader();
1642 DocumentLoadTiming* timing = documentLoader->timing();
1643 timing->markLoadEventStart();
1644 dispatchEvent(loadEvent, document());
1645 timing->markLoadEventEnd();
1647 dispatchEvent(loadEvent, document());
1649 // For load events, send a separate load event to the enclosing frame only.
1650 // This is a DOM extension and is independent of bubbling/capturing rules of
1652 Element* ownerElement = m_frame ? m_frame->ownerElement() : 0;
1654 ownerElement->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
1656 InspectorInstrumentation::loadEventFired(frame());
1659 bool DOMWindow::dispatchEvent(PassRefPtr<Event> prpEvent, PassRefPtr<EventTarget> prpTarget)
1661 RefPtr<EventTarget> protect = this;
1662 RefPtr<Event> event = prpEvent;
1664 event->setTarget(prpTarget ? prpTarget : this);
1665 event->setCurrentTarget(this);
1666 event->setEventPhase(Event::AT_TARGET);
1668 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), *event, this);
1670 bool result = fireEventListeners(event.get());
1672 InspectorInstrumentation::didDispatchEventOnWindow(cookie);
1677 void DOMWindow::removeAllEventListeners()
1679 EventTarget::removeAllEventListeners();
1681 #if ENABLE(DEVICE_ORIENTATION)
1682 if (DeviceMotionController* controller = DeviceMotionController::from(page()))
1683 controller->removeAllListeners(this);
1684 if (DeviceOrientationController* controller = DeviceOrientationController::from(page()))
1685 controller->removeAllListeners(this);
1688 removeAllUnloadEventListeners(this);
1689 removeAllBeforeUnloadEventListeners(this);
1692 void DOMWindow::captureEvents()
1697 void DOMWindow::releaseEvents()
1702 void DOMWindow::finishedLoading()
1704 if (m_shouldPrintWhenFinishedLoading) {
1705 m_shouldPrintWhenFinishedLoading = false;
1710 EventTargetData* DOMWindow::eventTargetData()
1712 return &m_eventTargetData;
1715 EventTargetData* DOMWindow::ensureEventTargetData()
1717 return &m_eventTargetData;
1720 void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow, SetLocationLocking locking)
1722 if (!isCurrentlyDisplayedInFrame())
1725 Document* activeDocument = activeWindow->document();
1726 if (!activeDocument)
1729 if (!activeDocument->canNavigate(m_frame))
1732 Frame* firstFrame = firstWindow->frame();
1736 KURL completedURL = firstFrame->document()->completeURL(urlString);
1737 if (completedURL.isNull())
1740 if (isInsecureScriptAccess(activeWindow, completedURL))
1743 // We want a new history item if we are processing a user gesture.
1744 m_frame->navigationScheduler()->scheduleLocationChange(activeDocument->securityOrigin(),
1745 // FIXME: What if activeDocument()->frame() is 0?
1746 completedURL, activeDocument->frame()->loader()->outgoingReferrer(),
1747 locking != LockHistoryBasedOnGestureState || !ScriptController::processingUserGesture(),
1748 locking != LockHistoryBasedOnGestureState);
1751 void DOMWindow::printErrorMessage(const String& message)
1753 if (message.isEmpty())
1756 Settings* settings = m_frame->settings();
1759 if (settings->privateBrowsingEnabled())
1762 // FIXME: Add arguments so that we can provide a correct source URL and line number.
1763 RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true);
1764 console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, stackTrace.release());
1767 String DOMWindow::crossDomainAccessErrorMessage(DOMWindow* activeWindow)
1769 const KURL& activeWindowURL = activeWindow->url();
1770 if (activeWindowURL.isNull())
1773 // FIXME: This error message should contain more specifics of why the same origin check has failed.
1774 // Perhaps we should involve the security origin object in composing it.
1775 // FIXME: This message, and other console messages, have extra newlines. Should remove them.
1776 return "Unsafe JavaScript attempt to access frame with URL " + m_url.string() + " from frame with URL " + activeWindowURL.string() + ". Domains, protocols and ports must match.\n";
1779 bool DOMWindow::isInsecureScriptAccess(DOMWindow* activeWindow, const String& urlString)
1781 if (!protocolIsJavaScript(urlString))
1784 // If this DOMWindow isn't currently active in the Frame, then there's no
1785 // way we should allow the access.
1786 // FIXME: Remove this check if we're able to disconnect DOMWindow from
1787 // Frame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054
1788 if (isCurrentlyDisplayedInFrame()) {
1789 // FIXME: Is there some way to eliminate the need for a separate "activeWindow == this" check?
1790 if (activeWindow == this)
1793 // FIXME: The name canAccess seems to be a roundabout way to ask "can execute script".
1794 // Can we name the SecurityOrigin function better to make this more clear?
1795 if (activeWindow->securityOrigin()->canAccess(securityOrigin()))
1799 printErrorMessage(crossDomainAccessErrorMessage(activeWindow));
1803 Frame* DOMWindow::createWindow(const String& urlString, const AtomicString& frameName, const WindowFeatures& windowFeatures,
1804 DOMWindow* activeWindow, Frame* firstFrame, Frame* openerFrame, PrepareDialogFunction function, void* functionContext)
1806 Frame* activeFrame = activeWindow->frame();
1808 // For whatever reason, Firefox uses the first frame to determine the outgoingReferrer. We replicate that behavior here.
1809 String referrer = firstFrame->loader()->outgoingReferrer();
1811 KURL completedURL = urlString.isEmpty() ? KURL(ParsedURLString, emptyString()) : firstFrame->document()->completeURL(urlString);
1812 if (!completedURL.isEmpty() && !completedURL.isValid()) {
1813 // Don't expose client code to invalid URLs.
1814 activeWindow->printErrorMessage("Unable to open a window with invalid URL '" + completedURL.string() + "'.\n");
1818 ResourceRequest request(completedURL, referrer);
1819 FrameLoader::addHTTPOriginIfNeeded(request, firstFrame->loader()->outgoingOrigin());
1820 FrameLoadRequest frameRequest(activeWindow->securityOrigin(), request, frameName);
1822 // We pass the opener frame for the lookupFrame in case the active frame is different from
1823 // the opener frame, and the name references a frame relative to the opener frame.
1825 Frame* newFrame = WebCore::createWindow(activeFrame, openerFrame, frameRequest, windowFeatures, created);
1829 newFrame->loader()->setOpener(openerFrame);
1830 newFrame->page()->setOpenedByDOM();
1832 if (newFrame->domWindow()->isInsecureScriptAccess(activeWindow, completedURL))
1836 function(newFrame->domWindow(), functionContext);
1839 newFrame->loader()->changeLocation(activeWindow->securityOrigin(), completedURL, referrer, false, false);
1840 else if (!urlString.isEmpty()) {
1841 bool lockHistory = !ScriptController::processingUserGesture();
1842 newFrame->navigationScheduler()->scheduleLocationChange(activeWindow->securityOrigin(), completedURL.string(), referrer, lockHistory, false);
1848 PassRefPtr<DOMWindow> DOMWindow::open(const String& urlString, const AtomicString& frameName, const String& windowFeaturesString,
1849 DOMWindow* activeWindow, DOMWindow* firstWindow)
1851 if (!isCurrentlyDisplayedInFrame())
1853 Document* activeDocument = activeWindow->document();
1854 if (!activeDocument)
1856 Frame* firstFrame = firstWindow->frame();
1860 if (!firstWindow->allowPopUp()) {
1861 // Because FrameTree::find() returns true for empty strings, we must check for empty frame names.
1862 // Otherwise, illegitimate window.open() calls with no name will pass right through the popup blocker.
1863 if (frameName.isEmpty() || !m_frame->tree()->find(frameName))
1867 // Get the target frame for the special cases of _top and _parent.
1868 // In those cases, we schedule a location change right now and return early.
1869 Frame* targetFrame = 0;
1870 if (frameName == "_top")
1871 targetFrame = m_frame->tree()->top();
1872 else if (frameName == "_parent") {
1873 if (Frame* parent = m_frame->tree()->parent())
1874 targetFrame = parent;
1876 targetFrame = m_frame;
1879 if (!activeDocument->canNavigate(targetFrame))
1882 KURL completedURL = firstFrame->document()->completeURL(urlString);
1884 if (targetFrame->domWindow()->isInsecureScriptAccess(activeWindow, completedURL))
1885 return targetFrame->domWindow();
1887 if (urlString.isEmpty())
1888 return targetFrame->domWindow();
1890 // For whatever reason, Firefox uses the first window rather than the active window to
1891 // determine the outgoing referrer. We replicate that behavior here.
1892 bool lockHistory = !ScriptController::processingUserGesture();
1893 targetFrame->navigationScheduler()->scheduleLocationChange(
1894 activeDocument->securityOrigin(),
1896 firstFrame->loader()->outgoingReferrer(),
1899 return targetFrame->domWindow();
1902 WindowFeatures windowFeatures(windowFeaturesString);
1903 FloatRect windowRect(windowFeatures.xSet ? windowFeatures.x : 0, windowFeatures.ySet ? windowFeatures.y : 0,
1904 windowFeatures.widthSet ? windowFeatures.width : 0, windowFeatures.heightSet ? windowFeatures.height : 0);
1905 Page* page = m_frame->page();
1906 DOMWindow::adjustWindowRect(screenAvailableRect(page ? page->mainFrame()->view() : 0), windowRect, windowRect);
1907 windowFeatures.x = windowRect.x();
1908 windowFeatures.y = windowRect.y();
1909 windowFeatures.height = windowRect.height();
1910 windowFeatures.width = windowRect.width();
1912 Frame* result = createWindow(urlString, frameName, windowFeatures, activeWindow, firstFrame, m_frame);
1913 return result ? result->domWindow() : 0;
1916 void DOMWindow::showModalDialog(const String& urlString, const String& dialogFeaturesString,
1917 DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction function, void* functionContext)
1919 if (!isCurrentlyDisplayedInFrame())
1921 Frame* activeFrame = activeWindow->frame();
1924 Frame* firstFrame = firstWindow->frame();
1928 if (!canShowModalDialogNow(m_frame) || !firstWindow->allowPopUp())
1931 Frame* dialogFrame = createWindow(urlString, emptyAtom, WindowFeatures(dialogFeaturesString, screenAvailableRect(m_frame->view())),
1932 activeWindow, firstFrame, m_frame, function, functionContext);
1936 dialogFrame->page()->chrome()->runModal();
1939 #if ENABLE(TIZEN_SEARCH_PROVIDER)
1940 External* DOMWindow::external() const
1942 if (!m_external && isCurrentlyDisplayedInFrame())
1943 m_external = External::create(m_frame);
1944 return m_external.get();
1947 } // namespace WebCore