1 /* 2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All Rights Reserved. 3 * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #include "config.h" 22 #include "Page.h" 23 24 #include "BackForwardList.h" 25 #include "Base64.h" 26 #include "CSSStyleSelector.h" 27 #include "Chrome.h" 28 #include "ChromeClient.h" 29 #include "ContextMenuClient.h" 30 #include "ContextMenuController.h" 31 #include "DOMWindow.h" 32 #include "DragController.h" 33 #include "ExceptionCode.h" 34 #include "EditorClient.h" 35 #include "EventNames.h" 36 #include "Event.h" 37 #include "FileSystem.h" 38 #include "FocusController.h" 39 #include "Frame.h" 40 #include "FrameLoader.h" 41 #include "FrameLoaderClient.h" 42 #include "FrameTree.h" 43 #include "FrameView.h" 44 #include "HTMLElement.h" 45 #include "HistoryItem.h" 46 #include "InspectorController.h" 47 #include "InspectorTimelineAgent.h" 48 #include "Logging.h" 49 #include "Navigator.h" 50 #include "NetworkStateNotifier.h" 51 #include "PageGroup.h" 52 #include "PluginData.h" 53 #include "PluginHalter.h" 54 #include "ProgressTracker.h" 55 #include "RenderWidget.h" 56 #include "RenderTheme.h" 57 #include "ScriptController.h" 58 #include "SelectionController.h" 59 #include "Settings.h" 60 #include "StringHash.h" 61 #include "TextResourceDecoder.h" 62 #include "Widget.h" 63 #include <wtf/HashMap.h> 64 #include <wtf/RefCountedLeakCounter.h> 65 #include <wtf/StdLibExtras.h> 66 67 #if ENABLE(DOM_STORAGE) 68 #include "StorageArea.h" 69 #include "StorageNamespace.h" 70 #endif 71 72 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) 73 #include "JavaScriptDebugServer.h" 74 #endif 75 76 #if ENABLE(WML) 77 #include "WMLPageState.h" 78 #endif 79 80 #if ENABLE(CLIENT_BASED_GEOLOCATION) 81 #include "GeolocationController.h" 82 #endif 83 84 #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) 85 #include "PackageNotifier.h" 86 #endif 87 88 namespace WebCore { 89 90 static HashSet<Page*>* allPages; 91 92 #ifndef NDEBUG 93 static WTF::RefCountedLeakCounter pageCounter("Page"); 94 #endif 95 96 static void networkStateChanged() 97 { 98 Vector<RefPtr<Frame> > frames; 99 100 // Get all the frames of all the pages in all the page groups 101 HashSet<Page*>::iterator end = allPages->end(); 102 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) { 103 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) 104 frames.append(frame); 105 } 106 107 AtomicString eventName = networkStateNotifier().onLine() ? eventNames().onlineEvent : eventNames().offlineEvent; 108 for (unsigned i = 0; i < frames.size(); i++) 109 frames[i]->document()->dispatchWindowEvent(Event::create(eventName, false, false)); 110 } 111 112 #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) 113 static void onPackageResultAvailable() 114 { 115 HashSet<Page*>::iterator end = allPages->end(); 116 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) { 117 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) 118 frame->domWindow()->navigator()->onPackageResult(); 119 } 120 } 121 #endif 122 123 Page::Page(ChromeClient* chromeClient, ContextMenuClient* contextMenuClient, EditorClient* editorClient, DragClient* dragClient, InspectorClient* inspectorClient, PluginHalterClient* pluginHalterClient, GeolocationControllerClient* geolocationControllerClient) 124 : m_chrome(new Chrome(this, chromeClient)) 125 , m_dragCaretController(new SelectionController(0, true)) 126 #if ENABLE(DRAG_SUPPORT) 127 , m_dragController(new DragController(this, dragClient)) 128 #endif 129 , m_focusController(new FocusController(this)) 130 #if ENABLE(CONTEXT_MENUS) 131 , m_contextMenuController(new ContextMenuController(this, contextMenuClient)) 132 #endif 133 #if ENABLE(INSPECTOR) 134 , m_inspectorController(new InspectorController(this, inspectorClient)) 135 #endif 136 #if ENABLE(CLIENT_BASED_GEOLOCATION) 137 , m_geolocationController(new GeolocationController(this, geolocationControllerClient)) 138 #endif 139 , m_settings(new Settings(this)) 140 , m_progress(new ProgressTracker) 141 , m_backForwardList(BackForwardList::create(this)) 142 , m_theme(RenderTheme::themeForPage(this)) 143 , m_editorClient(editorClient) 144 , m_frameCount(0) 145 , m_openedByDOM(false) 146 , m_tabKeyCyclesThroughElements(true) 147 , m_defersLoading(false) 148 , m_inLowQualityInterpolationMode(false) 149 , m_cookieEnabled(true) 150 , m_areMemoryCacheClientCallsEnabled(true) 151 , m_mediaVolume(1) 152 , m_javaScriptURLsAreAllowed(true) 153 #if ENABLE(INSPECTOR) 154 , m_parentInspectorController(0) 155 #endif 156 , m_didLoadUserStyleSheet(false) 157 , m_userStyleSheetModificationTime(0) 158 , m_group(0) 159 , m_debugger(0) 160 , m_customHTMLTokenizerTimeDelay(-1) 161 , m_customHTMLTokenizerChunkSize(-1) 162 , m_canStartPlugins(true) 163 { 164 #if !ENABLE(CONTEXT_MENUS) 165 UNUSED_PARAM(contextMenuClient); 166 #endif 167 #if !ENABLE(DRAG_SUPPORT) 168 UNUSED_PARAM(dragClient); 169 #endif 170 #if !ENABLE(INSPECTOR) 171 UNUSED_PARAM(inspectorClient); 172 #endif 173 #if !ENABLE(CLIENT_BASED_GEOLOCATION) 174 UNUSED_PARAM(geolocationControllerClient); 175 #endif 176 177 if (!allPages) { 178 allPages = new HashSet<Page*>; 179 180 networkStateNotifier().setNetworkStateChangedFunction(networkStateChanged); 181 #if PLATFORM(ANDROID) && ENABLE(APPLICATION_INSTALLED) 182 packageNotifier().setOnResultAvailable(onPackageResultAvailable); 183 #endif 184 } 185 186 ASSERT(!allPages->contains(this)); 187 allPages->add(this); 188 189 if (pluginHalterClient) { 190 m_pluginHalter.set(new PluginHalter(pluginHalterClient)); 191 m_pluginHalter->setPluginAllowedRunTime(m_settings->pluginAllowedRunTime()); 192 } 193 194 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) 195 JavaScriptDebugServer::shared().pageCreated(this); 196 #endif 197 198 #ifndef NDEBUG 199 pageCounter.increment(); 200 #endif 201 } 202 203 Page::~Page() 204 { 205 m_mainFrame->setView(0); 206 setGroupName(String()); 207 allPages->remove(this); 208 209 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) 210 frame->pageDestroyed(); 211 212 m_editorClient->pageDestroyed(); 213 #if ENABLE(INSPECTOR) 214 if (m_parentInspectorController) 215 m_parentInspectorController->pageDestroyed(); 216 m_inspectorController->inspectedPageDestroyed(); 217 #endif 218 219 m_backForwardList->close(); 220 221 #ifndef NDEBUG 222 pageCounter.decrement(); 223 224 // Cancel keepAlive timers, to ensure we release all Frames before exiting. 225 // It's safe to do this because we prohibit closing a Page while JavaScript 226 // is executing. 227 Frame::cancelAllKeepAlive(); 228 #endif 229 } 230 231 void Page::setMainFrame(PassRefPtr<Frame> mainFrame) 232 { 233 ASSERT(!m_mainFrame); // Should only be called during initialization 234 m_mainFrame = mainFrame; 235 } 236 237 bool Page::openedByDOM() const 238 { 239 return m_openedByDOM; 240 } 241 242 void Page::setOpenedByDOM() 243 { 244 m_openedByDOM = true; 245 } 246 247 BackForwardList* Page::backForwardList() 248 { 249 return m_backForwardList.get(); 250 } 251 252 bool Page::goBack() 253 { 254 HistoryItem* item = m_backForwardList->backItem(); 255 256 if (item) { 257 goToItem(item, FrameLoadTypeBack); 258 return true; 259 } 260 return false; 261 } 262 263 bool Page::goForward() 264 { 265 HistoryItem* item = m_backForwardList->forwardItem(); 266 267 if (item) { 268 goToItem(item, FrameLoadTypeForward); 269 return true; 270 } 271 return false; 272 } 273 274 bool Page::canGoBackOrForward(int distance) const 275 { 276 if (distance == 0) 277 return true; 278 if (distance > 0 && distance <= m_backForwardList->forwardListCount()) 279 return true; 280 if (distance < 0 && -distance <= m_backForwardList->backListCount()) 281 return true; 282 return false; 283 } 284 285 void Page::goBackOrForward(int distance) 286 { 287 if (distance == 0) 288 return; 289 290 HistoryItem* item = m_backForwardList->itemAtIndex(distance); 291 if (!item) { 292 if (distance > 0) { 293 int forwardListCount = m_backForwardList->forwardListCount(); 294 if (forwardListCount > 0) 295 item = m_backForwardList->itemAtIndex(forwardListCount); 296 } else { 297 int backListCount = m_backForwardList->backListCount(); 298 if (backListCount > 0) 299 item = m_backForwardList->itemAtIndex(-backListCount); 300 } 301 } 302 303 ASSERT(item); // we should not reach this line with an empty back/forward list 304 if (item) 305 goToItem(item, FrameLoadTypeIndexedBackForward); 306 } 307 308 void Page::goToItem(HistoryItem* item, FrameLoadType type) 309 { 310 // Abort any current load unless we're navigating the current document to a new state object 311 HistoryItem* currentItem = m_mainFrame->loader()->history()->currentItem(); 312 if (!item->stateObject() || !currentItem || item->documentSequenceNumber() != currentItem->documentSequenceNumber()) { 313 // Define what to do with any open database connections. By default we stop them and terminate the database thread. 314 DatabasePolicy databasePolicy = DatabasePolicyStop; 315 316 #if ENABLE(DATABASE) 317 // If we're navigating the history via a fragment on the same document, then we do not want to stop databases. 318 const KURL& currentURL = m_mainFrame->loader()->url(); 319 const KURL& newURL = item->url(); 320 321 if (newURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(currentURL, newURL)) 322 databasePolicy = DatabasePolicyContinue; 323 #endif 324 325 m_mainFrame->loader()->stopAllLoaders(databasePolicy); 326 } 327 328 m_mainFrame->loader()->history()->goToItem(item, type); 329 } 330 331 int Page::getHistoryLength() 332 { 333 return m_backForwardList->backListCount() + 1 + m_backForwardList->forwardListCount(); 334 } 335 336 void Page::setGlobalHistoryItem(HistoryItem* item) 337 { 338 m_globalHistoryItem = item; 339 } 340 341 void Page::setGroupName(const String& name) 342 { 343 if (m_group && !m_group->name().isEmpty()) { 344 ASSERT(m_group != m_singlePageGroup.get()); 345 ASSERT(!m_singlePageGroup); 346 m_group->removePage(this); 347 } 348 349 if (name.isEmpty()) 350 m_group = m_singlePageGroup.get(); 351 else { 352 m_singlePageGroup.clear(); 353 m_group = PageGroup::pageGroup(name); 354 m_group->addPage(this); 355 } 356 } 357 358 const String& Page::groupName() const 359 { 360 DEFINE_STATIC_LOCAL(String, nullString, ()); 361 return m_group ? m_group->name() : nullString; 362 } 363 364 void Page::initGroup() 365 { 366 ASSERT(!m_singlePageGroup); 367 ASSERT(!m_group); 368 m_singlePageGroup.set(new PageGroup(this)); 369 m_group = m_singlePageGroup.get(); 370 } 371 372 void Page::setNeedsReapplyStyles() 373 { 374 if (!allPages) 375 return; 376 HashSet<Page*>::iterator end = allPages->end(); 377 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) 378 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) 379 frame->setNeedsReapplyStyles(); 380 } 381 382 void Page::refreshPlugins(bool reload) 383 { 384 if (!allPages) 385 return; 386 387 PluginData::refresh(); 388 389 Vector<RefPtr<Frame> > framesNeedingReload; 390 391 HashSet<Page*>::iterator end = allPages->end(); 392 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) { 393 (*it)->m_pluginData = 0; 394 395 if (reload) { 396 for (Frame* frame = (*it)->mainFrame(); frame; frame = frame->tree()->traverseNext()) { 397 if (frame->loader()->containsPlugins()) 398 framesNeedingReload.append(frame); 399 } 400 } 401 } 402 403 for (size_t i = 0; i < framesNeedingReload.size(); ++i) 404 framesNeedingReload[i]->loader()->reload(); 405 } 406 407 PluginData* Page::pluginData() const 408 { 409 if (!settings()->arePluginsEnabled()) 410 return 0; 411 if (!m_pluginData) 412 m_pluginData = PluginData::create(this); 413 return m_pluginData.get(); 414 } 415 416 void Page::addUnstartedPlugin(PluginView* view) 417 { 418 ASSERT(!m_canStartPlugins); 419 m_unstartedPlugins.add(view); 420 } 421 422 void Page::removeUnstartedPlugin(PluginView* view) 423 { 424 ASSERT(!m_canStartPlugins); 425 ASSERT(m_unstartedPlugins.contains(view)); 426 m_unstartedPlugins.remove(view); 427 } 428 429 static Frame* incrementFrame(Frame* curr, bool forward, bool wrapFlag) 430 { 431 return forward 432 ? curr->tree()->traverseNextWithWrap(wrapFlag) 433 : curr->tree()->traversePreviousWithWrap(wrapFlag); 434 } 435 436 bool Page::findString(const String& target, TextCaseSensitivity caseSensitivity, FindDirection direction, bool shouldWrap) 437 { 438 if (target.isEmpty() || !mainFrame()) 439 return false; 440 441 Frame* frame = focusController()->focusedOrMainFrame(); 442 Frame* startFrame = frame; 443 do { 444 if (frame->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, false, true)) { 445 if (frame != startFrame) 446 startFrame->selection()->clear(); 447 focusController()->setFocusedFrame(frame); 448 return true; 449 } 450 frame = incrementFrame(frame, direction == FindDirectionForward, shouldWrap); 451 } while (frame && frame != startFrame); 452 453 // Search contents of startFrame, on the other side of the selection that we did earlier. 454 // We cheat a bit and just research with wrap on 455 if (shouldWrap && !startFrame->selection()->isNone()) { 456 bool found = startFrame->findString(target, direction == FindDirectionForward, caseSensitivity == TextCaseSensitive, true, true); 457 focusController()->setFocusedFrame(frame); 458 return found; 459 } 460 461 return false; 462 } 463 464 unsigned int Page::markAllMatchesForText(const String& target, TextCaseSensitivity caseSensitivity, bool shouldHighlight, unsigned limit) 465 { 466 if (target.isEmpty() || !mainFrame()) 467 return 0; 468 469 unsigned matches = 0; 470 471 Frame* frame = mainFrame(); 472 do { 473 frame->setMarkedTextMatchesAreHighlighted(shouldHighlight); 474 matches += frame->markAllMatchesForText(target, caseSensitivity == TextCaseSensitive, (limit == 0) ? 0 : (limit - matches)); 475 frame = incrementFrame(frame, true, false); 476 } while (frame); 477 478 return matches; 479 } 480 481 void Page::unmarkAllTextMatches() 482 { 483 if (!mainFrame()) 484 return; 485 486 Frame* frame = mainFrame(); 487 do { 488 frame->document()->removeMarkers(DocumentMarker::TextMatch); 489 frame = incrementFrame(frame, true, false); 490 } while (frame); 491 } 492 493 const VisibleSelection& Page::selection() const 494 { 495 return focusController()->focusedOrMainFrame()->selection()->selection(); 496 } 497 498 void Page::setDefersLoading(bool defers) 499 { 500 if (!m_settings->loadDeferringEnabled()) 501 return; 502 503 if (defers == m_defersLoading) 504 return; 505 506 m_defersLoading = defers; 507 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) 508 frame->loader()->setDefersLoading(defers); 509 } 510 511 void Page::clearUndoRedoOperations() 512 { 513 m_editorClient->clearUndoRedoOperations(); 514 } 515 516 bool Page::inLowQualityImageInterpolationMode() const 517 { 518 return m_inLowQualityInterpolationMode; 519 } 520 521 void Page::setInLowQualityImageInterpolationMode(bool mode) 522 { 523 m_inLowQualityInterpolationMode = mode; 524 } 525 526 void Page::setMediaVolume(float volume) 527 { 528 if (volume < 0 || volume > 1) 529 return; 530 531 if (m_mediaVolume == volume) 532 return; 533 534 m_mediaVolume = volume; 535 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { 536 frame->document()->mediaVolumeDidChange(); 537 } 538 } 539 540 void Page::didMoveOnscreen() 541 { 542 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { 543 if (frame->view()) 544 frame->view()->didMoveOnscreen(); 545 } 546 } 547 548 void Page::willMoveOffscreen() 549 { 550 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { 551 if (frame->view()) 552 frame->view()->willMoveOffscreen(); 553 } 554 } 555 556 void Page::userStyleSheetLocationChanged() 557 { 558 // FIXME: Eventually we will move to a model of just being handed the sheet 559 // text instead of loading the URL ourselves. 560 KURL url = m_settings->userStyleSheetLocation(); 561 if (url.isLocalFile()) 562 m_userStyleSheetPath = url.fileSystemPath(); 563 else 564 m_userStyleSheetPath = String(); 565 566 m_didLoadUserStyleSheet = false; 567 m_userStyleSheet = String(); 568 m_userStyleSheetModificationTime = 0; 569 570 // Data URLs with base64-encoded UTF-8 style sheets are common. We can process them 571 // synchronously and avoid using a loader. 572 if (url.protocolIs("data") && url.string().startsWith("data:text/css;charset=utf-8;base64,")) { 573 m_didLoadUserStyleSheet = true; 574 575 const unsigned prefixLength = 35; 576 Vector<char> encodedData(url.string().length() - prefixLength); 577 for (unsigned i = prefixLength; i < url.string().length(); ++i) 578 encodedData[i - prefixLength] = static_cast<char>(url.string()[i]); 579 580 Vector<char> styleSheetAsUTF8; 581 if (base64Decode(encodedData, styleSheetAsUTF8)) 582 m_userStyleSheet = String::fromUTF8(styleSheetAsUTF8.data(), styleSheetAsUTF8.size()); 583 } 584 585 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) { 586 if (frame->document()) 587 frame->document()->clearPageUserSheet(); 588 } 589 } 590 591 const String& Page::userStyleSheet() const 592 { 593 if (m_userStyleSheetPath.isEmpty()) 594 return m_userStyleSheet; 595 596 time_t modTime; 597 if (!getFileModificationTime(m_userStyleSheetPath, modTime)) { 598 // The stylesheet either doesn't exist, was just deleted, or is 599 // otherwise unreadable. If we've read the stylesheet before, we should 600 // throw away that data now as it no longer represents what's on disk. 601 m_userStyleSheet = String(); 602 return m_userStyleSheet; 603 } 604 605 // If the stylesheet hasn't changed since the last time we read it, we can 606 // just return the old data. 607 if (m_didLoadUserStyleSheet && modTime <= m_userStyleSheetModificationTime) 608 return m_userStyleSheet; 609 610 m_didLoadUserStyleSheet = true; 611 m_userStyleSheet = String(); 612 m_userStyleSheetModificationTime = modTime; 613 614 // FIXME: It would be better to load this asynchronously to avoid blocking 615 // the process, but we will first need to create an asynchronous loading 616 // mechanism that is not tied to a particular Frame. We will also have to 617 // determine what our behavior should be before the stylesheet is loaded 618 // and what should happen when it finishes loading, especially with respect 619 // to when the load event fires, when Document::close is called, and when 620 // layout/paint are allowed to happen. 621 RefPtr<SharedBuffer> data = SharedBuffer::createWithContentsOfFile(m_userStyleSheetPath); 622 if (!data) 623 return m_userStyleSheet; 624 625 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/css"); 626 m_userStyleSheet = decoder->decode(data->data(), data->size()); 627 m_userStyleSheet += decoder->flush(); 628 629 return m_userStyleSheet; 630 } 631 632 void Page::removeAllVisitedLinks() 633 { 634 if (!allPages) 635 return; 636 HashSet<PageGroup*> groups; 637 HashSet<Page*>::iterator pagesEnd = allPages->end(); 638 for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) { 639 if (PageGroup* group = (*it)->groupPtr()) 640 groups.add(group); 641 } 642 HashSet<PageGroup*>::iterator groupsEnd = groups.end(); 643 for (HashSet<PageGroup*>::iterator it = groups.begin(); it != groupsEnd; ++it) 644 (*it)->removeVisitedLinks(); 645 } 646 647 void Page::allVisitedStateChanged(PageGroup* group) 648 { 649 ASSERT(group); 650 if (!allPages) 651 return; 652 653 HashSet<Page*>::iterator pagesEnd = allPages->end(); 654 for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) { 655 Page* page = *it; 656 if (page->m_group != group) 657 continue; 658 for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) { 659 if (CSSStyleSelector* styleSelector = frame->document()->styleSelector()) 660 styleSelector->allVisitedStateChanged(); 661 } 662 } 663 } 664 665 void Page::visitedStateChanged(PageGroup* group, LinkHash visitedLinkHash) 666 { 667 ASSERT(group); 668 if (!allPages) 669 return; 670 671 HashSet<Page*>::iterator pagesEnd = allPages->end(); 672 for (HashSet<Page*>::iterator it = allPages->begin(); it != pagesEnd; ++it) { 673 Page* page = *it; 674 if (page->m_group != group) 675 continue; 676 for (Frame* frame = page->m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) { 677 if (CSSStyleSelector* styleSelector = frame->document()->styleSelector()) 678 styleSelector->visitedStateChanged(visitedLinkHash); 679 } 680 } 681 } 682 683 void Page::setDebuggerForAllPages(JSC::Debugger* debugger) 684 { 685 ASSERT(allPages); 686 687 HashSet<Page*>::iterator end = allPages->end(); 688 for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) 689 (*it)->setDebugger(debugger); 690 } 691 692 void Page::setDebugger(JSC::Debugger* debugger) 693 { 694 if (m_debugger == debugger) 695 return; 696 697 m_debugger = debugger; 698 699 for (Frame* frame = m_mainFrame.get(); frame; frame = frame->tree()->traverseNext()) 700 frame->script()->attachDebugger(m_debugger); 701 } 702 703 #if ENABLE(DOM_STORAGE) 704 StorageNamespace* Page::sessionStorage(bool optionalCreate) 705 { 706 if (!m_sessionStorage && optionalCreate) 707 m_sessionStorage = StorageNamespace::sessionStorageNamespace(this); 708 709 return m_sessionStorage.get(); 710 } 711 712 void Page::setSessionStorage(PassRefPtr<StorageNamespace> newStorage) 713 { 714 m_sessionStorage = newStorage; 715 } 716 #endif 717 718 #if ENABLE(WML) 719 WMLPageState* Page::wmlPageState() 720 { 721 if (!m_wmlPageState) 722 m_wmlPageState.set(new WMLPageState(this)); 723 return m_wmlPageState.get(); 724 } 725 #endif 726 727 void Page::setCustomHTMLTokenizerTimeDelay(double customHTMLTokenizerTimeDelay) 728 { 729 if (customHTMLTokenizerTimeDelay < 0) { 730 m_customHTMLTokenizerTimeDelay = -1; 731 return; 732 } 733 m_customHTMLTokenizerTimeDelay = customHTMLTokenizerTimeDelay; 734 } 735 736 void Page::setCustomHTMLTokenizerChunkSize(int customHTMLTokenizerChunkSize) 737 { 738 if (customHTMLTokenizerChunkSize < 0) { 739 m_customHTMLTokenizerChunkSize = -1; 740 return; 741 } 742 m_customHTMLTokenizerChunkSize = customHTMLTokenizerChunkSize; 743 } 744 745 void Page::setMemoryCacheClientCallsEnabled(bool enabled) 746 { 747 if (m_areMemoryCacheClientCallsEnabled == enabled) 748 return; 749 750 m_areMemoryCacheClientCallsEnabled = enabled; 751 if (!enabled) 752 return; 753 754 for (RefPtr<Frame> frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) 755 frame->loader()->tellClientAboutPastMemoryCacheLoads(); 756 } 757 758 void Page::setJavaScriptURLsAreAllowed(bool areAllowed) 759 { 760 m_javaScriptURLsAreAllowed = areAllowed; 761 } 762 763 bool Page::javaScriptURLsAreAllowed() const 764 { 765 return m_javaScriptURLsAreAllowed; 766 } 767 768 #if ENABLE(INSPECTOR) 769 InspectorTimelineAgent* Page::inspectorTimelineAgent() const 770 { 771 return m_inspectorController->timelineAgent(); 772 } 773 #endif 774 775 void Page::pluginAllowedRunTimeChanged() 776 { 777 if (m_pluginHalter) 778 m_pluginHalter->setPluginAllowedRunTime(m_settings->pluginAllowedRunTime()); 779 } 780 781 void Page::didStartPlugin(HaltablePlugin* obj) 782 { 783 if (m_pluginHalter) 784 m_pluginHalter->didStartPlugin(obj); 785 } 786 787 void Page::didStopPlugin(HaltablePlugin* obj) 788 { 789 if (m_pluginHalter) 790 m_pluginHalter->didStopPlugin(obj); 791 } 792 793 #if !ASSERT_DISABLED 794 void Page::checkFrameCountConsistency() const 795 { 796 ASSERT(m_frameCount >= 0); 797 798 int frameCount = 0; 799 for (Frame* frame = mainFrame(); frame; frame = frame->tree()->traverseNext()) 800 ++frameCount; 801 802 ASSERT(m_frameCount + 1 == frameCount); 803 } 804 #endif 805 } // namespace WebCore 806