OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. | |
3 * | |
4 * Redistribution and use in source and binary forms, with or without | |
5 * modification, are permitted provided that the following conditions | |
6 * are met: | |
7 * 1. Redistributions of source code must retain the above copyright | |
8 * notice, this list of conditions and the following disclaimer. | |
9 * 2. Redistributions in binary form must reproduce the above copyright | |
10 * notice, this list of conditions and the following disclaimer in the | |
11 * documentation and/or other materials provided with the distribution. | |
12 * | |
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 */ | |
25 | |
26 #include "config.h" | |
27 #include "DOMWindow.h" | |
28 | |
29 #include "BarInfo.h" | |
30 #include "CSSComputedStyleDeclaration.h" | |
31 #include "CSSRuleList.h" | |
32 #include "CSSStyleSelector.h" | |
33 #include "CString.h" | |
34 #include "Chrome.h" | |
35 #include "Console.h" | |
36 #include "DOMSelection.h" | |
37 #include "Document.h" | |
38 #include "Element.h" | |
39 #include "ExceptionCode.h" | |
40 #include "FloatRect.h" | |
41 #include "Frame.h" | |
42 #include "FrameLoader.h" | |
43 #include "FrameTree.h" | |
44 #include "FrameView.h" | |
45 #include "HTMLFrameOwnerElement.h" | |
46 #include "History.h" | |
47 #include "Location.h" | |
48 #include "MessageEvent.h" | |
49 #include "Navigator.h" | |
50 #include "Page.h" | |
51 #include "PageGroup.h" | |
52 #include "PlatformScreen.h" | |
53 #include "PlatformString.h" | |
54 #include "Screen.h" | |
55 #include "SecurityOrigin.h" | |
56 #include "Settings.h" | |
57 #include "ScriptController.h" | |
58 #include <algorithm> | |
59 #include <wtf/MathExtras.h> | |
60 | |
61 #if ENABLE(DATABASE) | |
62 #include "Database.h" | |
63 #endif | |
64 | |
65 #if ENABLE(DOM_STORAGE) | |
66 #include "LocalStorage.h" | |
67 #include "SessionStorage.h" | |
68 #include "Storage.h" | |
69 #include "StorageArea.h" | |
70 #endif | |
71 | |
72 #if ENABLE(OFFLINE_WEB_APPLICATIONS) | |
73 #include "DOMApplicationCache.h" | |
74 #endif | |
75 | |
76 using std::min; | |
77 using std::max; | |
78 | |
79 #if USE(V8) | |
80 #include "Location.h" | |
81 #include "Navigator.h" | |
82 #include "CString.h" | |
83 #include "FloatRect.h" | |
84 #include "FrameTree.h" | |
85 #include "FrameView.h" | |
86 #include "Page.h" | |
87 #include "Chrome.h" | |
88 #include "WindowFeatures.h" | |
89 #include "FrameLoadRequest.h" | |
90 #include "ScheduledAction.h" | |
91 #include "PausedTimeouts.h" | |
92 #include "v8_proxy.h" | |
93 | |
94 #if PLATFORM(WIN) | |
95 #include <windows.h> | |
96 #endif // WIN | |
97 | |
98 #include "CSSHelper.h" // parseURL | |
99 #endif // V8 | |
100 | |
101 | |
102 namespace WebCore { | |
103 | |
104 class PostMessageTimer : public TimerBase { | |
105 public: | |
106 PostMessageTimer(DOMWindow* window, PassRefPtr<MessageEvent> event, Security
Origin* targetOrigin) | |
107 : m_window(window) | |
108 , m_event(event) | |
109 , m_targetOrigin(targetOrigin) | |
110 { | |
111 } | |
112 | |
113 MessageEvent* event() const { return m_event.get(); } | |
114 SecurityOrigin* targetOrigin() const { return m_targetOrigin.get(); } | |
115 | |
116 private: | |
117 virtual void fired() | |
118 { | |
119 m_window->postMessageTimerFired(this); | |
120 } | |
121 | |
122 RefPtr<DOMWindow> m_window; | |
123 RefPtr<MessageEvent> m_event; | |
124 RefPtr<SecurityOrigin> m_targetOrigin; | |
125 }; | |
126 | |
127 // This function: | |
128 // 1) Validates the pending changes are not changing to NaN | |
129 // 2) Constrains the window rect to no smaller than 100 in each dimension and no | |
130 // bigger than the the float rect's dimensions. | |
131 // 3) Constrain window rect to within the top and left boundaries of the screen
rect | |
132 // 4) Constraint the window rect to within the bottom and right boundaries of th
e | |
133 // screen rect. | |
134 // 5) Translate the window rect coordinates to be within the coordinate space of | |
135 // the screen rect. | |
136 void DOMWindow::adjustWindowRect(const FloatRect& screen, FloatRect& window, con
st FloatRect& pendingChanges) | |
137 { | |
138 // Make sure we're in a valid state before adjusting dimensions. | |
139 ASSERT(isfinite(screen.x())); | |
140 ASSERT(isfinite(screen.y())); | |
141 ASSERT(isfinite(screen.width())); | |
142 ASSERT(isfinite(screen.height())); | |
143 ASSERT(isfinite(window.x())); | |
144 ASSERT(isfinite(window.y())); | |
145 ASSERT(isfinite(window.width())); | |
146 ASSERT(isfinite(window.height())); | |
147 | |
148 // Update window values if new requested values are not NaN. | |
149 if (!isnan(pendingChanges.x())) | |
150 window.setX(pendingChanges.x()); | |
151 if (!isnan(pendingChanges.y())) | |
152 window.setY(pendingChanges.y()); | |
153 if (!isnan(pendingChanges.width())) | |
154 window.setWidth(pendingChanges.width()); | |
155 if (!isnan(pendingChanges.height())) | |
156 window.setHeight(pendingChanges.height()); | |
157 | |
158 // Resize the window to between 100 and the screen width and height. | |
159 window.setWidth(min(max(100.0f, window.width()), screen.width())); | |
160 window.setHeight(min(max(100.0f, window.height()), screen.height())); | |
161 | |
162 // Constrain the window position to the screen. | |
163 window.setX(max(screen.x(), min(window.x(), screen.right() - window.width())
)); | |
164 window.setY(max(screen.y(), min(window.y(), screen.bottom() - window.height(
)))); | |
165 } | |
166 | |
167 #if USE(V8) | |
168 | |
169 static int lastUsedTimeoutId; | |
170 static int timerNestingLevel = 0; | |
171 const int kMaxTimerNestingLevel = 5; | |
172 const double kMinimumTimerInterval = 0.001; // Change this to speed up Javascri
pt's setTimeout! | |
173 | |
174 class DOMWindowTimer : public TimerBase { | |
175 public: | |
176 DOMWindowTimer(int timeoutId, int nestingLevel, | |
177 DOMWindow* o, ScheduledAction* a) | |
178 : m_timeoutId(timeoutId), m_nestingLevel(nestingLevel), | |
179 m_object(o), m_action(a) { } | |
180 | |
181 virtual ~DOMWindowTimer() { delete m_action; } | |
182 | |
183 int timeoutId() const { return m_timeoutId; } | |
184 | |
185 int nestingLevel() const { return m_nestingLevel; } | |
186 void setNestingLevel(int n) { m_nestingLevel = n; } | |
187 | |
188 ScheduledAction* action() const { return m_action; } | |
189 ScheduledAction* takeAction() { ScheduledAction* a = m_action; m_action = 0;
return a; } | |
190 | |
191 private: | |
192 virtual void fired(); | |
193 | |
194 int m_timeoutId; | |
195 int m_nestingLevel; | |
196 DOMWindow* m_object; | |
197 ScheduledAction* m_action; | |
198 }; | |
199 | |
200 void DOMWindowTimer::fired() { | |
201 timerNestingLevel = m_nestingLevel; | |
202 m_object->timerFired(this); | |
203 timerNestingLevel = 0; | |
204 } | |
205 | |
206 #endif // V8 | |
207 | |
208 | |
209 DOMWindow::DOMWindow(Frame* frame) | |
210 : m_frame(frame) | |
211 { | |
212 } | |
213 | |
214 DOMWindow::~DOMWindow() | |
215 { | |
216 if (m_frame) | |
217 m_frame->clearFormerDOMWindow(this); | |
218 } | |
219 | |
220 void DOMWindow::disconnectFrame() | |
221 { | |
222 m_frame = 0; | |
223 clear(); | |
224 } | |
225 | |
226 void DOMWindow::clear() | |
227 { | |
228 if (m_screen) | |
229 m_screen->disconnectFrame(); | |
230 m_screen = 0; | |
231 | |
232 if (m_selection) | |
233 m_selection->disconnectFrame(); | |
234 m_selection = 0; | |
235 | |
236 if (m_history) | |
237 m_history->disconnectFrame(); | |
238 m_history = 0; | |
239 | |
240 if (m_locationbar) | |
241 m_locationbar->disconnectFrame(); | |
242 m_locationbar = 0; | |
243 | |
244 if (m_menubar) | |
245 m_menubar->disconnectFrame(); | |
246 m_menubar = 0; | |
247 | |
248 if (m_personalbar) | |
249 m_personalbar->disconnectFrame(); | |
250 m_personalbar = 0; | |
251 | |
252 if (m_scrollbars) | |
253 m_scrollbars->disconnectFrame(); | |
254 m_scrollbars = 0; | |
255 | |
256 if (m_statusbar) | |
257 m_statusbar->disconnectFrame(); | |
258 m_statusbar = 0; | |
259 | |
260 if (m_toolbar) | |
261 m_toolbar->disconnectFrame(); | |
262 m_toolbar = 0; | |
263 | |
264 if (m_console) | |
265 m_console->disconnectFrame(); | |
266 m_console = 0; | |
267 | |
268 if (m_navigator) | |
269 m_navigator->disconnectFrame(); | |
270 m_navigator = 0; | |
271 | |
272 if (m_location) | |
273 m_location->disconnectFrame(); | |
274 m_location = 0; | |
275 | |
276 #if ENABLE(DOM_STORAGE) | |
277 if (m_sessionStorage) | |
278 m_sessionStorage->disconnectFrame(); | |
279 m_sessionStorage = 0; | |
280 | |
281 if (m_localStorage) | |
282 m_localStorage->disconnectFrame(); | |
283 m_localStorage = 0; | |
284 #endif | |
285 | |
286 #if ENABLE(OFFLINE_WEB_APPLICATIONS) | |
287 if (m_applicationCache) | |
288 m_applicationCache->disconnectFrame(); | |
289 m_applicationCache = 0; | |
290 #endif | |
291 } | |
292 | |
293 Screen* DOMWindow::screen() const | |
294 { | |
295 if (!m_screen) | |
296 m_screen = Screen::create(m_frame); | |
297 return m_screen.get(); | |
298 } | |
299 | |
300 History* DOMWindow::history() const | |
301 { | |
302 if (!m_history) | |
303 m_history = History::create(m_frame); | |
304 return m_history.get(); | |
305 } | |
306 | |
307 BarInfo* DOMWindow::locationbar() const | |
308 { | |
309 if (!m_locationbar) | |
310 m_locationbar = BarInfo::create(m_frame, BarInfo::Locationbar); | |
311 return m_locationbar.get(); | |
312 } | |
313 | |
314 BarInfo* DOMWindow::menubar() const | |
315 { | |
316 if (!m_menubar) | |
317 m_menubar = BarInfo::create(m_frame, BarInfo::Menubar); | |
318 return m_menubar.get(); | |
319 } | |
320 | |
321 BarInfo* DOMWindow::personalbar() const | |
322 { | |
323 if (!m_personalbar) | |
324 m_personalbar = BarInfo::create(m_frame, BarInfo::Personalbar); | |
325 return m_personalbar.get(); | |
326 } | |
327 | |
328 BarInfo* DOMWindow::scrollbars() const | |
329 { | |
330 if (!m_scrollbars) | |
331 m_scrollbars = BarInfo::create(m_frame, BarInfo::Scrollbars); | |
332 return m_scrollbars.get(); | |
333 } | |
334 | |
335 BarInfo* DOMWindow::statusbar() const | |
336 { | |
337 if (!m_statusbar) | |
338 m_statusbar = BarInfo::create(m_frame, BarInfo::Statusbar); | |
339 return m_statusbar.get(); | |
340 } | |
341 | |
342 BarInfo* DOMWindow::toolbar() const | |
343 { | |
344 if (!m_toolbar) | |
345 m_toolbar = BarInfo::create(m_frame, BarInfo::Toolbar); | |
346 return m_toolbar.get(); | |
347 } | |
348 | |
349 Console* DOMWindow::console() const | |
350 { | |
351 if (!m_console) | |
352 m_console = Console::create(m_frame); | |
353 return m_console.get(); | |
354 } | |
355 | |
356 #if ENABLE(OFFLINE_WEB_APPLICATIONS) | |
357 DOMApplicationCache* DOMWindow::applicationCache() const | |
358 { | |
359 if (!m_applicationCache) | |
360 m_applicationCache = DOMApplicationCache::create(m_frame); | |
361 return m_applicationCache.get(); | |
362 } | |
363 #endif | |
364 | |
365 Navigator* DOMWindow::navigator() const | |
366 { | |
367 if (!m_navigator) | |
368 m_navigator = Navigator::create(m_frame); | |
369 return m_navigator.get(); | |
370 } | |
371 | |
372 Location* DOMWindow::location() const | |
373 { | |
374 if (!m_location) | |
375 m_location = Location::create(m_frame); | |
376 return m_location.get(); | |
377 } | |
378 | |
379 #if ENABLE(DOM_STORAGE) | |
380 Storage* DOMWindow::sessionStorage() const | |
381 { | |
382 if (m_sessionStorage) | |
383 return m_sessionStorage.get(); | |
384 | |
385 Page* page = m_frame->page(); | |
386 if (!page) | |
387 return 0; | |
388 | |
389 Document* document = m_frame->document(); | |
390 if (!document) | |
391 return 0; | |
392 | |
393 RefPtr<StorageArea> storageArea = page->sessionStorage()->storageArea(docume
nt->securityOrigin()); | |
394 m_sessionStorage = Storage::create(m_frame, storageArea.release()); | |
395 return m_sessionStorage.get(); | |
396 } | |
397 | |
398 Storage* DOMWindow::localStorage() const | |
399 { | |
400 Document* document = this->document(); | |
401 if (!document) | |
402 return 0; | |
403 | |
404 Page* page = document->page(); | |
405 if (!page) | |
406 return 0; | |
407 | |
408 LocalStorage* localStorage = page->group().localStorage(); | |
409 RefPtr<StorageArea> storageArea = localStorage ? localStorage->storageArea(m
_frame, document->securityOrigin()) : 0; | |
410 if (storageArea) | |
411 m_localStorage = Storage::create(m_frame, storageArea.release()); | |
412 | |
413 return m_localStorage.get(); | |
414 } | |
415 #endif | |
416 | |
417 void DOMWindow::postMessage(const String& message, const String& targetOrigin, D
OMWindow* source, ExceptionCode& ec) | |
418 { | |
419 if (!m_frame) | |
420 return; | |
421 | |
422 // Compute the target origin. We need to do this synchronously in order | |
423 // to generate the SYNTAX_ERR exception correctly. | |
424 RefPtr<SecurityOrigin> target; | |
425 if (targetOrigin != "*") { | |
426 target = SecurityOrigin::create(KURL(targetOrigin)); | |
427 if (target->isEmpty()) { | |
428 ec = SYNTAX_ERR; | |
429 return; | |
430 } | |
431 } | |
432 | |
433 // Capture the source of the message. We need to do this synchronously | |
434 // in order to capture the source of the message correctly. | |
435 Document* sourceDocument = source->document(); | |
436 if (!sourceDocument) | |
437 return; | |
438 String sourceOrigin = sourceDocument->securityOrigin()->toString(); | |
439 | |
440 // Schedule the message. | |
441 PostMessageTimer* timer = new PostMessageTimer(this, MessageEvent::create(me
ssage, sourceOrigin, "", source), target.get()); | |
442 timer->startOneShot(0); | |
443 } | |
444 | |
445 void DOMWindow::postMessageTimerFired(PostMessageTimer* t) | |
446 { | |
447 OwnPtr<PostMessageTimer> timer(t); | |
448 | |
449 if (!document()) | |
450 return; | |
451 | |
452 if (timer->targetOrigin()) { | |
453 // Check target origin now since the target document may have changed si
nce the simer was scheduled. | |
454 if (!timer->targetOrigin()->isSameSchemeHostPort(document()->securityOri
gin())) { | |
455 String message = String::format("Unable to post message to %s. Recip
ient has origin %s.\n", | |
456 timer->targetOrigin()->toString().utf8().data(), document()->sec
urityOrigin()->toString().utf8().data()); | |
457 console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 0
, String()); | |
458 return; | |
459 } | |
460 } | |
461 | |
462 document()->dispatchWindowEvent(timer->event()); | |
463 } | |
464 | |
465 DOMSelection* DOMWindow::getSelection() | |
466 { | |
467 if (!m_selection) | |
468 m_selection = DOMSelection::create(m_frame); | |
469 return m_selection.get(); | |
470 } | |
471 | |
472 Element* DOMWindow::frameElement() const | |
473 { | |
474 if (!m_frame) | |
475 return 0; | |
476 | |
477 return m_frame->ownerElement(); | |
478 } | |
479 | |
480 void DOMWindow::focus() | |
481 { | |
482 if (!m_frame) | |
483 return; | |
484 | |
485 m_frame->focusWindow(); | |
486 } | |
487 | |
488 void DOMWindow::blur() | |
489 { | |
490 if (!m_frame) | |
491 return; | |
492 | |
493 m_frame->unfocusWindow(); | |
494 } | |
495 | |
496 void DOMWindow::close() | |
497 { | |
498 if (!m_frame) | |
499 return; | |
500 | |
501 Settings* settings = m_frame->settings(); | |
502 bool allow_scripts_to_close_windows = | |
503 (settings && settings->allowScriptsToCloseWindows()); | |
504 | |
505 if (m_frame->loader()->openedByDOM() | |
506 || m_frame->loader()->getHistoryLength() <= 1 | |
507 || allow_scripts_to_close_windows) | |
508 m_frame->scheduleClose(); | |
509 } | |
510 | |
511 void DOMWindow::print() | |
512 { | |
513 if (!m_frame) | |
514 return; | |
515 | |
516 Page* page = m_frame->page(); | |
517 if (!page) | |
518 return; | |
519 | |
520 page->chrome()->print(m_frame); | |
521 } | |
522 | |
523 void DOMWindow::stop() | |
524 { | |
525 if (!m_frame) | |
526 return; | |
527 | |
528 // Ignores stop() in unload event handlers | |
529 if (m_frame->loader()->firingUnloadEvents()) | |
530 return; | |
531 | |
532 // We must check whether the load is complete asynchronously, | |
533 // because we might still be parsing the document until the | |
534 // callstack unwinds. | |
535 m_frame->loader()->stopForUserCancel(true); | |
536 } | |
537 | |
538 void DOMWindow::alert(const String& message) | |
539 { | |
540 #if USE(V8) | |
541 // Before showing the JavaScript dialog, we give | |
542 // the proxy implementation a chance to process any | |
543 // pending console messages. | |
544 V8Proxy::ProcessConsoleMessages(); | |
545 #endif | |
546 | |
547 if (!m_frame) | |
548 return; | |
549 | |
550 Document* doc = m_frame->document(); | |
551 ASSERT(doc); | |
552 if (doc) | |
553 doc->updateRendering(); | |
554 | |
555 Page* page = m_frame->page(); | |
556 if (!page) | |
557 return; | |
558 | |
559 page->chrome()->runJavaScriptAlert(m_frame, message); | |
560 } | |
561 | |
562 bool DOMWindow::confirm(const String& message) | |
563 { | |
564 #if USE(V8) | |
565 // Before showing the JavaScript dialog, we give | |
566 // the proxy implementation a chance to process any | |
567 // pending console messages. | |
568 V8Proxy::ProcessConsoleMessages(); | |
569 #endif | |
570 | |
571 if (!m_frame) | |
572 return false; | |
573 | |
574 Document* doc = m_frame->document(); | |
575 ASSERT(doc); | |
576 if (doc) | |
577 doc->updateRendering(); | |
578 | |
579 Page* page = m_frame->page(); | |
580 if (!page) | |
581 return false; | |
582 | |
583 return page->chrome()->runJavaScriptConfirm(m_frame, message); | |
584 } | |
585 | |
586 String DOMWindow::prompt(const String& message, const String& defaultValue) | |
587 { | |
588 #if USE(V8) | |
589 // Before showing the JavaScript dialog, we give | |
590 // the proxy implementation a chance to process any | |
591 // pending console messages. | |
592 V8Proxy::ProcessConsoleMessages(); | |
593 #endif | |
594 | |
595 if (!m_frame) | |
596 return String(); | |
597 | |
598 Document* doc = m_frame->document(); | |
599 ASSERT(doc); | |
600 if (doc) | |
601 doc->updateRendering(); | |
602 | |
603 Page* page = m_frame->page(); | |
604 if (!page) | |
605 return String(); | |
606 | |
607 String returnValue; | |
608 if (page->chrome()->runJavaScriptPrompt(m_frame, message, defaultValue, retu
rnValue)) | |
609 return returnValue; | |
610 | |
611 return String(); | |
612 } | |
613 | |
614 bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, b
ool wrap, bool wholeWord, bool searchInFrames, bool showDialog) const | |
615 { | |
616 if (!m_frame) | |
617 return false; | |
618 | |
619 // FIXME (13016): Support wholeWord, searchInFrames and showDialog | |
620 return m_frame->findString(string, !backwards, caseSensitive, wrap, false); | |
621 } | |
622 | |
623 bool DOMWindow::offscreenBuffering() const | |
624 { | |
625 return true; | |
626 } | |
627 | |
628 int DOMWindow::outerHeight() const | |
629 { | |
630 if (!m_frame) | |
631 return 0; | |
632 | |
633 Page* page = m_frame->page(); | |
634 if (!page) | |
635 return 0; | |
636 | |
637 return static_cast<int>(page->chrome()->windowRect().height()); | |
638 } | |
639 | |
640 int DOMWindow::outerWidth() const | |
641 { | |
642 if (!m_frame) | |
643 return 0; | |
644 | |
645 Page* page = m_frame->page(); | |
646 if (!page) | |
647 return 0; | |
648 | |
649 return static_cast<int>(page->chrome()->windowRect().width()); | |
650 } | |
651 | |
652 int DOMWindow::innerHeight() const | |
653 { | |
654 if (!m_frame) | |
655 return 0; | |
656 | |
657 FrameView* view = m_frame->view(); | |
658 if (!view) | |
659 return 0; | |
660 | |
661 return static_cast<int>(view->height() / m_frame->pageZoomFactor()); | |
662 } | |
663 | |
664 int DOMWindow::innerWidth() const | |
665 { | |
666 if (!m_frame) | |
667 return 0; | |
668 | |
669 FrameView* view = m_frame->view(); | |
670 if (!view) | |
671 return 0; | |
672 | |
673 return static_cast<int>(view->width() / m_frame->pageZoomFactor()); | |
674 } | |
675 | |
676 int DOMWindow::screenX() const | |
677 { | |
678 if (!m_frame) | |
679 return 0; | |
680 | |
681 Page* page = m_frame->page(); | |
682 if (!page) | |
683 return 0; | |
684 | |
685 return static_cast<int>(page->chrome()->windowRect().x()); | |
686 } | |
687 | |
688 int DOMWindow::screenY() const | |
689 { | |
690 if (!m_frame) | |
691 return 0; | |
692 | |
693 Page* page = m_frame->page(); | |
694 if (!page) | |
695 return 0; | |
696 | |
697 return static_cast<int>(page->chrome()->windowRect().y()); | |
698 } | |
699 | |
700 int DOMWindow::scrollX() const | |
701 { | |
702 if (!m_frame) | |
703 return 0; | |
704 | |
705 FrameView* view = m_frame->view(); | |
706 if (!view) | |
707 return 0; | |
708 | |
709 Document* doc = m_frame->document(); | |
710 ASSERT(doc); | |
711 if (doc) | |
712 doc->updateLayoutIgnorePendingStylesheets(); | |
713 | |
714 return static_cast<int>(view->contentsX() / m_frame->pageZoomFactor()); | |
715 } | |
716 | |
717 int DOMWindow::scrollY() const | |
718 { | |
719 if (!m_frame) | |
720 return 0; | |
721 | |
722 FrameView* view = m_frame->view(); | |
723 if (!view) | |
724 return 0; | |
725 | |
726 Document* doc = m_frame->document(); | |
727 ASSERT(doc); | |
728 if (doc) | |
729 doc->updateLayoutIgnorePendingStylesheets(); | |
730 | |
731 return static_cast<int>(view->contentsY() / m_frame->pageZoomFactor()); | |
732 } | |
733 | |
734 bool DOMWindow::closed() const | |
735 { | |
736 return !m_frame; | |
737 } | |
738 | |
739 unsigned DOMWindow::length() const | |
740 { | |
741 if (!m_frame) | |
742 return 0; | |
743 | |
744 return m_frame->tree()->childCount(); | |
745 } | |
746 | |
747 String DOMWindow::name() const | |
748 { | |
749 if (!m_frame) | |
750 return String(); | |
751 | |
752 return m_frame->tree()->name(); | |
753 } | |
754 | |
755 void DOMWindow::setName(const String& string) | |
756 { | |
757 if (!m_frame) | |
758 return; | |
759 | |
760 m_frame->tree()->setName(string); | |
761 } | |
762 | |
763 String DOMWindow::status() const | |
764 { | |
765 if (!m_frame) | |
766 return String(); | |
767 | |
768 return m_frame->jsStatusBarText(); | |
769 } | |
770 | |
771 void DOMWindow::setStatus(const String& string) | |
772 { | |
773 if (!m_frame) | |
774 return; | |
775 | |
776 m_frame->setJSStatusBarText(string); | |
777 } | |
778 | |
779 String DOMWindow::defaultStatus() const | |
780 { | |
781 if (!m_frame) | |
782 return String(); | |
783 | |
784 return m_frame->jsDefaultStatusBarText(); | |
785 } | |
786 | |
787 void DOMWindow::setDefaultStatus(const String& string) | |
788 { | |
789 if (!m_frame) | |
790 return; | |
791 | |
792 m_frame->setJSDefaultStatusBarText(string); | |
793 } | |
794 | |
795 DOMWindow* DOMWindow::self() const | |
796 { | |
797 if (!m_frame) | |
798 return 0; | |
799 | |
800 return m_frame->domWindow(); | |
801 } | |
802 | |
803 DOMWindow* DOMWindow::opener() const | |
804 { | |
805 if (!m_frame) | |
806 return 0; | |
807 | |
808 Frame* opener = m_frame->loader()->opener(); | |
809 if (!opener) | |
810 return 0; | |
811 | |
812 return opener->domWindow(); | |
813 } | |
814 | |
815 DOMWindow* DOMWindow::parent() const | |
816 { | |
817 if (!m_frame) | |
818 return 0; | |
819 | |
820 Frame* parent = m_frame->tree()->parent(true); | |
821 if (parent) | |
822 return parent->domWindow(); | |
823 | |
824 return m_frame->domWindow(); | |
825 } | |
826 | |
827 DOMWindow* DOMWindow::top() const | |
828 { | |
829 if (!m_frame) | |
830 return 0; | |
831 | |
832 Page* page = m_frame->page(); | |
833 if (!page) | |
834 return 0; | |
835 | |
836 return m_frame->tree()->top(true)->domWindow(); | |
837 } | |
838 | |
839 Document* DOMWindow::document() const | |
840 { | |
841 if (!m_frame) | |
842 return 0; | |
843 | |
844 ASSERT(m_frame->document()); | |
845 return m_frame->document(); | |
846 } | |
847 | |
848 PassRefPtr<CSSStyleDeclaration> DOMWindow::getComputedStyle(Element* elt, const
String&) const | |
849 { | |
850 if (!elt) | |
851 return 0; | |
852 | |
853 // FIXME: This needs take pseudo elements into account. | |
854 return computedStyle(elt); | |
855 } | |
856 | |
857 PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* elt, const String
& pseudoElt, bool authorOnly) const | |
858 { | |
859 if (!m_frame) | |
860 return 0; | |
861 | |
862 Document* doc = m_frame->document(); | |
863 ASSERT(doc); | |
864 if (!doc) | |
865 return 0; | |
866 | |
867 if (!pseudoElt.isEmpty()) | |
868 return doc->styleSelector()->pseudoStyleRulesForElement(elt, pseudoElt,
authorOnly); | |
869 return doc->styleSelector()->styleRulesForElement(elt, authorOnly); | |
870 } | |
871 | |
872 double DOMWindow::devicePixelRatio() const | |
873 { | |
874 if (!m_frame) | |
875 return 0.0; | |
876 | |
877 Page* page = m_frame->page(); | |
878 if (!page) | |
879 return 0.0; | |
880 | |
881 return page->chrome()->scaleFactor(); | |
882 } | |
883 | |
884 #if USE(V8) | |
885 | |
886 static void setWindowFeature(const String& keyString, const String& valueString,
WindowFeatures& windowFeatures) { | |
887 int value; | |
888 | |
889 if (valueString.length() == 0 || // listing a key with no value is shorthand f
or key=yes | |
890 valueString == "yes") | |
891 value = 1; | |
892 else | |
893 value = valueString.toInt(); | |
894 | |
895 if (keyString == "left" || keyString == "screenx") { | |
896 windowFeatures.xSet = true; | |
897 windowFeatures.x = value; | |
898 } else if (keyString == "top" || keyString == "screeny") { | |
899 windowFeatures.ySet = true; | |
900 windowFeatures.y = value; | |
901 } else if (keyString == "width" || keyString == "innerwidth") { | |
902 windowFeatures.widthSet = true; | |
903 windowFeatures.width = value; | |
904 } else if (keyString == "height" || keyString == "innerheight") { | |
905 windowFeatures.heightSet = true; | |
906 windowFeatures.height = value; | |
907 } else if (keyString == "menubar") | |
908 windowFeatures.menuBarVisible = value; | |
909 else if (keyString == "toolbar") | |
910 windowFeatures.toolBarVisible = value; | |
911 else if (keyString == "location") | |
912 windowFeatures.locationBarVisible = value; | |
913 else if (keyString == "status") | |
914 windowFeatures.statusBarVisible = value; | |
915 else if (keyString == "resizable") | |
916 windowFeatures.resizable = value; | |
917 else if (keyString == "fullscreen") | |
918 windowFeatures.fullscreen = value; | |
919 else if (keyString == "scrollbars") | |
920 windowFeatures.scrollbarsVisible = value; | |
921 } | |
922 | |
923 | |
924 void DOMWindow::back() | |
925 { | |
926 if (m_history) | |
927 m_history->back(); | |
928 } | |
929 | |
930 void DOMWindow::forward() | |
931 { | |
932 if (m_history) | |
933 m_history->forward(); | |
934 } | |
935 | |
936 Location* DOMWindow::location() | |
937 { | |
938 if (!m_location) | |
939 m_location = Location::create(m_frame); | |
940 return m_location.get(); | |
941 } | |
942 | |
943 void DOMWindow::setLocation(const String& v) { | |
944 if (!m_frame) | |
945 return; | |
946 | |
947 Frame* active_frame = ScriptController::retrieveActiveFrame(); | |
948 if (!active_frame) | |
949 return; | |
950 | |
951 if (!active_frame->loader()->shouldAllowNavigation(m_frame)) | |
952 return; | |
953 | |
954 if (!parseURL(v).startsWith("javascript:", false) || | |
955 ScriptController::isSafeScript(m_frame)) { | |
956 String completed_url = active_frame->loader()->completeURL(v).string(); | |
957 | |
958 m_frame->loader()->scheduleLocationChange(completed_url, | |
959 active_frame->loader()->outgoingReferrer(), false, | |
960 active_frame->script()->processingUserGesture()); | |
961 } | |
962 } | |
963 | |
964 Navigator* DOMWindow::navigator() | |
965 { | |
966 if (!m_navigator) | |
967 m_navigator = Navigator::create(m_frame); | |
968 | |
969 return m_navigator.get(); | |
970 } | |
971 | |
972 void DOMWindow::dump(const String& msg) | |
973 { | |
974 if (!m_frame) | |
975 return; | |
976 | |
977 m_frame->domWindow()->console()->addMessage(JSMessageSource, | |
978 ErrorMessageLevel, msg, 0, m_frame->document()->url()); | |
979 } | |
980 | |
981 void DOMWindow::scheduleClose() | |
982 { | |
983 if (!m_frame) | |
984 return; | |
985 | |
986 m_frame->scheduleClose(); | |
987 } | |
988 | |
989 void DOMWindow::timerFired(DOMWindowTimer* timer) { | |
990 if (!m_frame) | |
991 return; | |
992 | |
993 // Simple case for non-one-shot timers. | |
994 if (timer->isActive()) { | |
995 int timeoutId = timer->timeoutId(); | |
996 | |
997 timer->action()->execute(this); | |
998 return; | |
999 } | |
1000 | |
1001 // Delete timer before executing the action for one-shot timers. | |
1002 ScheduledAction* action = timer->takeAction(); | |
1003 m_timeouts.remove(timer->timeoutId()); | |
1004 delete timer; | |
1005 action->execute(this); | |
1006 delete action; | |
1007 } | |
1008 | |
1009 | |
1010 void DOMWindow::clearAllTimeouts() | |
1011 { | |
1012 deleteAllValues(m_timeouts); | |
1013 m_timeouts.clear(); | |
1014 } | |
1015 | |
1016 int DOMWindow::installTimeout(ScheduledAction* a, int t, bool singleShot) { | |
1017 if (!m_frame) | |
1018 return 0; | |
1019 | |
1020 int timeoutId = ++lastUsedTimeoutId; | |
1021 | |
1022 // avoid wraparound going negative on us | |
1023 if (timeoutId <= 0) | |
1024 timeoutId = 1; | |
1025 | |
1026 int nestLevel = timerNestingLevel + 1; | |
1027 | |
1028 DOMWindowTimer* timer = new DOMWindowTimer(timeoutId, nestLevel, this, a); | |
1029 ASSERT(!m_timeouts.get(timeoutId)); | |
1030 m_timeouts.set(timeoutId, timer); | |
1031 double interval = max(kMinimumTimerInterval, t * 0.001); | |
1032 if (singleShot) | |
1033 timer->startOneShot(interval); | |
1034 else | |
1035 timer->startRepeating(interval); | |
1036 | |
1037 return timeoutId; | |
1038 } | |
1039 | |
1040 void DOMWindow::clearTimeout(int timeoutId) | |
1041 { | |
1042 // timeout IDs have to be positive, and 0 and -1 are unsafe to | |
1043 // even look up since they are the empty and deleted value | |
1044 // respectively | |
1045 if (timeoutId <= 0) | |
1046 return; | |
1047 | |
1048 delete m_timeouts.take(timeoutId); | |
1049 } | |
1050 | |
1051 void DOMWindow::pauseTimeouts(OwnPtr<PausedTimeouts>& pausedTimeouts) | |
1052 { | |
1053 size_t count = m_timeouts.size(); | |
1054 if (count == 0) { | |
1055 pausedTimeouts.clear(); | |
1056 return; | |
1057 } | |
1058 | |
1059 PausedTimeout* t = new PausedTimeout[count]; | |
1060 PausedTimeouts* result = new PausedTimeouts(t, count); | |
1061 | |
1062 TimeoutsMap::iterator it = m_timeouts.begin(); | |
1063 for (size_t i = 0; i != count; ++i, ++it) { | |
1064 int timeoutId = it->first; | |
1065 DOMWindowTimer* timer = it->second; | |
1066 t[i].timeoutId = timeoutId; | |
1067 t[i].nestingLevel = timer->nestingLevel(); | |
1068 t[i].nextFireInterval = timer->nextFireInterval(); | |
1069 t[i].repeatInterval = timer->repeatInterval(); | |
1070 t[i].action = timer->takeAction(); | |
1071 } | |
1072 ASSERT(it == m_timeouts.end()); | |
1073 | |
1074 deleteAllValues(m_timeouts); | |
1075 m_timeouts.clear(); | |
1076 | |
1077 pausedTimeouts.set(result); | |
1078 } | |
1079 | |
1080 void DOMWindow::resumeTimeouts(OwnPtr<PausedTimeouts>& timeouts) { | |
1081 if (!timeouts) | |
1082 return; | |
1083 size_t count = timeouts->numTimeouts(); | |
1084 PausedTimeout* array = timeouts->takeTimeouts(); | |
1085 for (size_t i = 0; i != count; ++i) { | |
1086 int timeoutId = array[i].timeoutId; | |
1087 DOMWindowTimer* timer = | |
1088 new DOMWindowTimer(timeoutId, array[i].nestingLevel, | |
1089 this, array[i].action); | |
1090 m_timeouts.set(timeoutId, timer); | |
1091 timer->start(array[i].nextFireInterval, array[i].repeatInterval); | |
1092 } | |
1093 delete[] array; | |
1094 timeouts.clear(); | |
1095 } | |
1096 | |
1097 #endif // V8 | |
1098 | |
1099 void DOMWindow::updateLayout() const { | |
1100 WebCore::Document* docimpl = m_frame->document(); | |
1101 if (docimpl) | |
1102 docimpl->updateLayoutIgnorePendingStylesheets(); | |
1103 } | |
1104 | |
1105 void DOMWindow::moveTo(float x, float y) const { | |
1106 if (!m_frame || !m_frame->page()) return; | |
1107 | |
1108 Page* page = m_frame->page(); | |
1109 FloatRect fr = page->chrome()->windowRect(); | |
1110 FloatRect sr = screenAvailableRect(page->mainFrame()->view()); | |
1111 fr.setLocation(sr.location()); | |
1112 FloatRect update = fr; | |
1113 update.move(x, y); | |
1114 // Security check (the spec talks about UniversalBrowserWrite to disable this
check...) | |
1115 adjustWindowRect(sr, fr, update); | |
1116 page->chrome()->setWindowRect(fr); | |
1117 } | |
1118 | |
1119 void DOMWindow::moveBy(float x, float y) const { | |
1120 if (!m_frame || !m_frame->page()) return; | |
1121 | |
1122 Page* page = m_frame->page(); | |
1123 FloatRect fr = page->chrome()->windowRect(); | |
1124 FloatRect update = fr; | |
1125 update.move(x, y); | |
1126 // Security check (the spec talks about UniversalBrowserWrite to disable this
check...) | |
1127 adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update); | |
1128 page->chrome()->setWindowRect(fr); | |
1129 } | |
1130 | |
1131 void DOMWindow::resizeTo(float x, float y) const { | |
1132 if (!m_frame || !m_frame->page()) return; | |
1133 | |
1134 Page* page = m_frame->page(); | |
1135 FloatRect fr = page->chrome()->windowRect(); | |
1136 FloatSize dest = FloatSize(x, y); | |
1137 FloatRect update(fr.location(), dest); | |
1138 adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update); | |
1139 page->chrome()->setWindowRect(fr); | |
1140 } | |
1141 | |
1142 void DOMWindow::resizeBy(float x, float y) const { | |
1143 if (!m_frame || !m_frame->page()) return; | |
1144 | |
1145 Page* page = m_frame->page(); | |
1146 FloatRect fr = page->chrome()->windowRect(); | |
1147 FloatSize dest = fr.size() + FloatSize(x, y); | |
1148 FloatRect update(fr.location(), dest); | |
1149 adjustWindowRect(screenAvailableRect(page->mainFrame()->view()), fr, update); | |
1150 page->chrome()->setWindowRect(fr); | |
1151 } | |
1152 | |
1153 | |
1154 void DOMWindow::scrollTo(int x, int y) const { | |
1155 if (!m_frame || !m_frame->view()) | |
1156 return; | |
1157 | |
1158 if (m_frame->isDisconnected()) | |
1159 return; | |
1160 | |
1161 updateLayout(); | |
1162 m_frame->view()->setContentsPos(x, y); | |
1163 } | |
1164 | |
1165 void DOMWindow::scrollBy(int x, int y) const { | |
1166 if (!m_frame || !m_frame->view()) return; | |
1167 | |
1168 updateLayout(); | |
1169 m_frame->view()->scrollBy(x, y); | |
1170 } | |
1171 | |
1172 #if ENABLE(DATABASE) | |
1173 PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& v
ersion, const String& displayName, unsigned long estimatedSize, ExceptionCode& e
c) | |
1174 { | |
1175 if (!m_frame) | |
1176 return 0; | |
1177 return; | |
1178 | |
1179 if (m_frame->isDisconnected()) | |
1180 return; | |
1181 | |
1182 Document* doc = m_frame->document(); | |
1183 ASSERT(doc); | |
1184 if (!doc) | |
1185 return 0; | |
1186 | |
1187 return Database::openDatabase(doc, name, version, displayName, estimatedSize
, ec); | |
1188 } | |
1189 #endif | |
1190 | |
1191 | |
1192 } // namespace WebCore | |
OLD | NEW |