| 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 |