| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
| 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * | 9 * |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 // <rdar://problem/3979539> back/forward cache navigations should consult po
licy delegate | 229 // <rdar://problem/3979539> back/forward cache navigations should consult po
licy delegate |
| 230 Page* page = m_frame->page(); | 230 Page* page = m_frame->page(); |
| 231 if (!page) | 231 if (!page) |
| 232 return; | 232 return; |
| 233 if (!m_frame->loader()->client()->shouldGoToHistoryItem(targetItem)) | 233 if (!m_frame->loader()->client()->shouldGoToHistoryItem(targetItem)) |
| 234 return; | 234 return; |
| 235 | 235 |
| 236 // Set the BF cursor before commit, which lets the user quickly click back/f
orward again. | 236 // Set the BF cursor before commit, which lets the user quickly click back/f
orward again. |
| 237 // - plus, it only makes sense for the top level of the operation through th
e frametree, | 237 // - plus, it only makes sense for the top level of the operation through th
e frametree, |
| 238 // as opposed to happening for some/one of the page commits that might happe
n soon | 238 // as opposed to happening for some/one of the page commits that might happe
n soon |
| 239 HistoryItem* currentItem = page->backForward()->currentItem(); | 239 RefPtr<HistoryItem> currentItem = page->backForward()->currentItem(); |
| 240 page->backForward()->setCurrentItem(targetItem); | 240 page->backForward()->setCurrentItem(targetItem); |
| 241 Settings* settings = m_frame->settings(); | 241 Settings* settings = m_frame->settings(); |
| 242 page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled())
? 0 : targetItem); | 242 page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled())
? 0 : targetItem); |
| 243 | 243 |
| 244 // First set the provisional item of any frames that are not actually naviga
ting. | 244 // First set the provisional item of any frames that are not actually naviga
ting. |
| 245 // This must be done before trying to navigate the desired frame, because so
me | 245 // This must be done before trying to navigate the desired frame, because so
me |
| 246 // navigations can commit immediately (such as about:blank). We must be sur
e that | 246 // navigations can commit immediately (such as about:blank). We must be sur
e that |
| 247 // all frames have provisional items set before the commit. | 247 // all frames have provisional items set before the commit. |
| 248 recursiveSetProvisionalItem(targetItem, currentItem, type); | 248 recursiveSetProvisionalItem(targetItem, currentItem.get(), type); |
| 249 // Now that all other frames have provisional items, do the actual navigatio
n. | 249 // Now that all other frames have provisional items, do the actual navigatio
n. |
| 250 recursiveGoToItem(targetItem, currentItem, type); | 250 recursiveGoToItem(targetItem, currentItem.get(), type); |
| 251 } | 251 } |
| 252 | 252 |
| 253 void HistoryController::updateForBackForwardNavigation() | 253 void HistoryController::updateForBackForwardNavigation() |
| 254 { | 254 { |
| 255 #if !LOG_DISABLED | 255 #if !LOG_DISABLED |
| 256 if (m_frame->loader()->documentLoader()) | 256 if (m_frame->loader()->documentLoader()) |
| 257 LOG(History, "WebCoreHistory: Updating History for back/forward navigati
on in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); | 257 LOG(History, "WebCoreHistory: Updating History for back/forward navigati
on in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); |
| 258 #endif | 258 #endif |
| 259 | 259 |
| 260 // Must grab the current scroll position before disturbing it | 260 // Must grab the current scroll position before disturbing it |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 } | 395 } |
| 396 | 396 |
| 397 void HistoryController::updateForCommit() | 397 void HistoryController::updateForCommit() |
| 398 { | 398 { |
| 399 FrameLoader* frameLoader = m_frame->loader(); | 399 FrameLoader* frameLoader = m_frame->loader(); |
| 400 #if !LOG_DISABLED | 400 #if !LOG_DISABLED |
| 401 if (frameLoader->documentLoader()) | 401 if (frameLoader->documentLoader()) |
| 402 LOG(History, "WebCoreHistory: Updating History for commit in frame %s",
frameLoader->documentLoader()->title().utf8().data()); | 402 LOG(History, "WebCoreHistory: Updating History for commit in frame %s",
frameLoader->documentLoader()->title().utf8().data()); |
| 403 #endif | 403 #endif |
| 404 FrameLoadType type = frameLoader->loadType(); | 404 FrameLoadType type = frameLoader->loadType(); |
| 405 if (isBackForwardLoadType(type) || | 405 if (isBackForwardLoadType(type) |
| 406 ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin)
&& !frameLoader->provisionalDocumentLoader()->unreachableURL().isEmpty())) { | 406 || isReplaceLoadTypeWithProvisionalItem(type) |
| 407 || ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigi
n) && !frameLoader->provisionalDocumentLoader()->unreachableURL().isEmpty())) { |
| 407 // Once committed, we want to use current item for saving DocState, and | 408 // Once committed, we want to use current item for saving DocState, and |
| 408 // the provisional item for restoring state. | 409 // the provisional item for restoring state. |
| 409 // Note previousItem must be set before we close the URL, which will | 410 // Note previousItem must be set before we close the URL, which will |
| 410 // happen when the data source is made non-provisional below | 411 // happen when the data source is made non-provisional below |
| 411 m_frameLoadComplete = false; | 412 m_frameLoadComplete = false; |
| 412 m_previousItem = m_currentItem; | 413 m_previousItem = m_currentItem; |
| 413 ASSERT(m_provisionalItem); | 414 ASSERT(m_provisionalItem); |
| 414 m_currentItem = m_provisionalItem; | 415 m_currentItem = m_provisionalItem; |
| 415 m_provisionalItem = 0; | 416 m_provisionalItem = 0; |
| 416 | 417 |
| 417 // Tell all other frames in the tree to commit their provisional items a
nd | 418 // Tell all other frames in the tree to commit their provisional items a
nd |
| 418 // restore their scroll position. We'll avoid this frame (which has alr
eady | 419 // restore their scroll position. We'll avoid this frame (which has alr
eady |
| 419 // committed) and its children (which will be replaced). | 420 // committed) and its children (which will be replaced). |
| 420 Page* page = m_frame->page(); | 421 Page* page = m_frame->page(); |
| 421 ASSERT(page); | 422 ASSERT(page); |
| 422 page->mainFrame()->loader()->history()->recursiveUpdateForCommit(); | 423 page->mainFrame()->loader()->history()->recursiveUpdateForCommit(); |
| 423 } | 424 } |
| 424 } | 425 } |
| 425 | 426 |
| 427 bool HistoryController::isReplaceLoadTypeWithProvisionalItem(FrameLoadType type) |
| 428 { |
| 429 // Going back to an error page in a subframe can trigger a FrameLoadTypeRepl
ace |
| 430 // while m_provisionalItem is set, so we need to commit it. |
| 431 return type == FrameLoadTypeReplace && m_provisionalItem; |
| 432 } |
| 433 |
| 426 void HistoryController::recursiveUpdateForCommit() | 434 void HistoryController::recursiveUpdateForCommit() |
| 427 { | 435 { |
| 428 // The frame that navigated will now have a null provisional item. | 436 // The frame that navigated will now have a null provisional item. |
| 429 // Ignore it and its children. | 437 // Ignore it and its children. |
| 430 if (!m_provisionalItem) | 438 if (!m_provisionalItem) |
| 431 return; | 439 return; |
| 432 | 440 |
| 433 // For each frame that already had the content the item requested (based on | 441 // For each frame that already had the content the item requested (based on |
| 434 // (a matching URL and frame tree snapshot), just restore the scroll positio
n. | 442 // (a matching URL and frame tree snapshot), just restore the scroll positio
n. |
| 435 // Save form state (works from currentItem, since m_frameLoadComplete is tru
e) | 443 // Save form state (works from currentItem, since m_frameLoadComplete is tru
e) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 464 | 472 |
| 465 Settings* settings = m_frame->settings(); | 473 Settings* settings = m_frame->settings(); |
| 466 if (!settings || settings->privateBrowsingEnabled()) | 474 if (!settings || settings->privateBrowsingEnabled()) |
| 467 return; | 475 return; |
| 468 | 476 |
| 469 Page* page = m_frame->page(); | 477 Page* page = m_frame->page(); |
| 470 if (!page) | 478 if (!page) |
| 471 return; | 479 return; |
| 472 | 480 |
| 473 addVisitedLink(page, m_frame->loader()->url()); | 481 addVisitedLink(page, m_frame->loader()->url()); |
| 482 page->mainFrame()->loader()->history()->recursiveUpdateForSameDocumentNaviga
tion(); |
| 483 } |
| 484 |
| 485 void HistoryController::recursiveUpdateForSameDocumentNavigation() |
| 486 { |
| 487 // The frame that navigated will now have a null provisional item. |
| 488 // Ignore it and its children. |
| 489 if (!m_provisionalItem) |
| 490 return; |
| 491 |
| 492 // Commit the provisional item. |
| 493 m_frameLoadComplete = false; |
| 494 m_previousItem = m_currentItem; |
| 495 m_currentItem = m_provisionalItem; |
| 496 m_provisionalItem = 0; |
| 497 |
| 498 // Iterate over the rest of the tree. |
| 499 for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tre
e()->nextSibling()) |
| 500 child->loader()->history()->recursiveUpdateForSameDocumentNavigation(); |
| 474 } | 501 } |
| 475 | 502 |
| 476 void HistoryController::updateForFrameLoadCompleted() | 503 void HistoryController::updateForFrameLoadCompleted() |
| 477 { | 504 { |
| 478 // Even if already complete, we might have set a previous item on a frame th
at | 505 // Even if already complete, we might have set a previous item on a frame th
at |
| 479 // didn't do any data loading on the past transaction. Make sure to track th
at | 506 // didn't do any data loading on the past transaction. Make sure to track th
at |
| 480 // the load is complete so that we use the current item instead. | 507 // the load is complete so that we use the current item instead. |
| 481 m_frameLoadComplete = true; | 508 m_frameLoadComplete = true; |
| 482 } | 509 } |
| 483 | 510 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 613 ASSERT(item); | 640 ASSERT(item); |
| 614 ASSERT(fromItem); | 641 ASSERT(fromItem); |
| 615 | 642 |
| 616 if (itemsAreClones(item, fromItem)) { | 643 if (itemsAreClones(item, fromItem)) { |
| 617 // Set provisional item, which will be committed in recursiveUpdateForCo
mmit. | 644 // Set provisional item, which will be committed in recursiveUpdateForCo
mmit. |
| 618 m_provisionalItem = item; | 645 m_provisionalItem = item; |
| 619 | 646 |
| 620 const HistoryItemVector& childItems = item->children(); | 647 const HistoryItemVector& childItems = item->children(); |
| 621 | 648 |
| 622 int size = childItems.size(); | 649 int size = childItems.size(); |
| 650 |
| 623 for (int i = 0; i < size; ++i) { | 651 for (int i = 0; i < size; ++i) { |
| 624 String childFrameName = childItems[i]->target(); | 652 String childFrameName = childItems[i]->target(); |
| 625 HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFram
eName); | 653 HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFram
eName); |
| 626 ASSERT(fromChildItem); | 654 ASSERT(fromChildItem); |
| 627 Frame* childFrame = m_frame->tree()->child(childFrameName); | 655 Frame* childFrame = m_frame->tree()->child(childFrameName); |
| 628 ASSERT(childFrame); | 656 ASSERT(childFrame); |
| 629 childFrame->loader()->history()->recursiveSetProvisionalItem(childIt
ems[i].get(), fromChildItem, type); | 657 childFrame->loader()->history()->recursiveSetProvisionalItem(childIt
ems[i].get(), fromChildItem, type); |
| 630 } | 658 } |
| 631 } | 659 } |
| 632 } | 660 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 651 ASSERT(childFrame); | 679 ASSERT(childFrame); |
| 652 childFrame->loader()->history()->recursiveGoToItem(childItems[i].get
(), fromChildItem, type); | 680 childFrame->loader()->history()->recursiveGoToItem(childItems[i].get
(), fromChildItem, type); |
| 653 } | 681 } |
| 654 } else { | 682 } else { |
| 655 m_frame->loader()->loadItem(item, type); | 683 m_frame->loader()->loadItem(item, type); |
| 656 } | 684 } |
| 657 } | 685 } |
| 658 | 686 |
| 659 bool HistoryController::itemsAreClones(HistoryItem* item1, HistoryItem* item2) c
onst | 687 bool HistoryController::itemsAreClones(HistoryItem* item1, HistoryItem* item2) c
onst |
| 660 { | 688 { |
| 661 // It appears that one of the items can be null in release builds, leading | |
| 662 // to the crashes seen in http://webkit.org/b/52819. For now, try to | |
| 663 // narrow it down with a more specific crash. | |
| 664 if (!item1) | |
| 665 CRASH(); | |
| 666 if (!item2) | |
| 667 CRASH(); | |
| 668 | |
| 669 // If the item we're going to is a clone of the item we're at, then we do | 689 // If the item we're going to is a clone of the item we're at, then we do |
| 670 // not need to load it again. The current frame tree and the frame tree | 690 // not need to load it again. The current frame tree and the frame tree |
| 671 // snapshot in the item have to match. | 691 // snapshot in the item have to match. |
| 672 // Note: Some clients treat a navigation to the current history item as | 692 // Note: Some clients treat a navigation to the current history item as |
| 673 // a reload. Thus, if item1 and item2 are the same, we need to create a | 693 // a reload. Thus, if item1 and item2 are the same, we need to create a |
| 674 // new document and should not consider them clones. | 694 // new document and should not consider them clones. |
| 675 // (See http://webkit.org/b/35532 for details.) | 695 // (See http://webkit.org/b/35532 for details.) |
| 676 return item1 != item2 | 696 return item1 != item2 |
| 677 && item1->itemSequenceNumber() == item2->itemSequenceNumber() | 697 && item1->itemSequenceNumber() == item2->itemSequenceNumber() |
| 678 && currentFramesMatchItem(item1) | 698 && currentFramesMatchItem(item1) |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 if (!m_currentItem) | 793 if (!m_currentItem) |
| 774 return; | 794 return; |
| 775 | 795 |
| 776 if (!urlString.isEmpty()) | 796 if (!urlString.isEmpty()) |
| 777 m_currentItem->setURLString(urlString); | 797 m_currentItem->setURLString(urlString); |
| 778 m_currentItem->setTitle(title); | 798 m_currentItem->setTitle(title); |
| 779 m_currentItem->setStateObject(stateObject); | 799 m_currentItem->setStateObject(stateObject); |
| 780 } | 800 } |
| 781 | 801 |
| 782 } // namespace WebCore | 802 } // namespace WebCore |
| OLD | NEW |