Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(528)

Side by Side Diff: third_party/WebKit/Source/core/loader/FrameLoader.cpp

Issue 2949073002: Changing scroll and view state in onpopstate shouldn't overwrite back/forward state restore (Closed)
Patch Set: Reset ViewState when trying to copy from a nullptr Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
3 * reserved. 3 * reserved.
4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 4 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
5 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. 5 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
6 * (http://www.torchmobile.com/) 6 * (http://www.torchmobile.com/)
7 * Copyright (C) 2008 Alp Toker <alp@atoker.com> 7 * Copyright (C) 2008 Alp Toker <alp@atoker.com>
8 * Copyright (C) Research In Motion Limited 2009. All rights reserved. 8 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
9 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com> 9 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
10 * Copyright (C) 2011 Google Inc. All rights reserved. 10 * Copyright (C) 2011 Google Inc. All rights reserved.
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 if (history_item) 584 if (history_item)
585 document_loader_->SetItemForHistoryNavigation(history_item); 585 document_loader_->SetItemForHistoryNavigation(history_item);
586 UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr, 586 UpdateForSameDocumentNavigation(url, kSameDocumentNavigationDefault, nullptr,
587 kScrollRestorationAuto, frame_load_type, 587 kScrollRestorationAuto, frame_load_type,
588 initiating_document); 588 initiating_document);
589 589
590 document_loader_->GetInitialScrollState().was_scrolled_by_user = false; 590 document_loader_->GetInitialScrollState().was_scrolled_by_user = false;
591 591
592 frame_->GetDocument()->CheckCompleted(); 592 frame_->GetDocument()->CheckCompleted();
593 593
594 // onpopstate might change view state, so stash for later restore.
595 std::unique_ptr<HistoryItem::ViewState> view_state;
596 if (history_item && history_item->GetViewState()) {
597 view_state =
598 WTF::MakeUnique<HistoryItem::ViewState>(*history_item->GetViewState());
599 }
600
594 frame_->DomWindow()->StatePopped(state_object 601 frame_->DomWindow()->StatePopped(state_object
595 ? std::move(state_object) 602 ? std::move(state_object)
596 : SerializedScriptValue::NullValue()); 603 : SerializedScriptValue::NullValue());
597 604
598 if (history_item) { 605 if (history_item) {
599 RestoreScrollPositionAndViewStateForLoadType(frame_load_type, 606 RestoreScrollPositionAndViewState(frame_load_type, kHistorySameDocumentLoad,
600 kHistorySameDocumentLoad); 607 view_state.get(),
608 history_item->ScrollRestorationType());
601 } 609 }
602 610
603 // We need to scroll to the fragment whether or not a hash change occurred, 611 // We need to scroll to the fragment whether or not a hash change occurred,
604 // since the user might have scrolled since the previous navigation. 612 // since the user might have scrolled since the previous navigation.
605 ProcessFragment(url, frame_load_type, kNavigationWithinSameDocument); 613 ProcessFragment(url, frame_load_type, kNavigationWithinSameDocument);
606 614
607 TakeObjectSnapshot(); 615 TakeObjectSnapshot();
608 } 616 }
609 617
610 // static 618 // static
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
1086 Client()->TransitionToCommittedForNewPage(); 1094 Client()->TransitionToCommittedForNewPage();
1087 1095
1088 frame_->GetNavigationScheduler().Cancel(); 1096 frame_->GetNavigationScheduler().Cancel();
1089 } 1097 }
1090 1098
1091 bool FrameLoader::IsLoadingMainFrame() const { 1099 bool FrameLoader::IsLoadingMainFrame() const {
1092 return frame_->IsMainFrame(); 1100 return frame_->IsMainFrame();
1093 } 1101 }
1094 1102
1095 void FrameLoader::RestoreScrollPositionAndViewState() { 1103 void FrameLoader::RestoreScrollPositionAndViewState() {
1096 if (!frame_->GetPage() || !GetDocumentLoader()) 1104 if (!frame_->GetPage() || !GetDocumentLoader() ||
1105 !GetDocumentLoader()->GetHistoryItem())
1097 return; 1106 return;
1098 RestoreScrollPositionAndViewStateForLoadType(GetDocumentLoader()->LoadType(), 1107 RestoreScrollPositionAndViewState(
1099 kHistoryDifferentDocumentLoad); 1108 GetDocumentLoader()->LoadType(), kHistoryDifferentDocumentLoad,
1109 GetDocumentLoader()->GetHistoryItem()->GetViewState(),
1110 GetDocumentLoader()->GetHistoryItem()->ScrollRestorationType());
1100 } 1111 }
1101 1112
1102 void FrameLoader::RestoreScrollPositionAndViewStateForLoadType( 1113 void FrameLoader::RestoreScrollPositionAndViewState(
1103 FrameLoadType load_type, 1114 FrameLoadType load_type,
1104 HistoryLoadType history_load_type) { 1115 HistoryLoadType history_load_type,
1116 HistoryItem::ViewState* view_state,
1117 HistoryScrollRestorationType scroll_restoration_type) {
1105 LocalFrameView* view = frame_->View(); 1118 LocalFrameView* view = frame_->View();
1106 if (!view || !view->LayoutViewportScrollableArea() || 1119 if (!view || !view->LayoutViewportScrollableArea() ||
1107 !state_machine_.CommittedFirstRealDocumentLoad() || 1120 !state_machine_.CommittedFirstRealDocumentLoad() ||
1108 !frame_->IsAttached()) { 1121 !frame_->IsAttached()) {
1109 return; 1122 return;
1110 } 1123 }
1111 if (!NeedsHistoryItemRestore(load_type)) 1124 if (!NeedsHistoryItemRestore(load_type) || !view_state)
1112 return;
1113 HistoryItem* history_item = document_loader_->GetHistoryItem();
1114 if (!history_item || !history_item->DidSaveScrollOrScaleState())
1115 return; 1125 return;
1116 1126
1117 bool should_restore_scroll = 1127 bool should_restore_scroll =
1118 history_item->ScrollRestorationType() != kScrollRestorationManual; 1128 scroll_restoration_type != kScrollRestorationManual;
1119 bool should_restore_scale = history_item->PageScaleFactor(); 1129 bool should_restore_scale = view_state->page_scale_factor_;
1120 1130
1121 // This tries to balance: 1131 // This tries to balance:
1122 // 1. restoring as soon as possible. 1132 // 1. restoring as soon as possible.
1123 // 2. not overriding user scroll (TODO(majidvp): also respect user scale). 1133 // 2. not overriding user scroll (TODO(majidvp): also respect user scale).
1124 // 3. detecting clamping to avoid repeatedly popping the scroll position down 1134 // 3. detecting clamping to avoid repeatedly popping the scroll position down
1125 // as the page height increases. 1135 // as the page height increases.
1126 // 4. forcing a layout if necessary to avoid clamping. 1136 // 4. forcing a layout if necessary to avoid clamping.
1127 // 5. ignoring clamp detection if scroll state is not being restored, if load 1137 // 5. ignoring clamp detection if scroll state is not being restored, if load
1128 // is complete, or if the navigation is same-document (as the new page may 1138 // is complete, or if the navigation is same-document (as the new page may
1129 // be smaller than the previous page). 1139 // be smaller than the previous page).
1130 bool can_restore_without_clamping = 1140 bool can_restore_without_clamping =
1131 view->LayoutViewportScrollableArea()->ClampScrollOffset( 1141 view->LayoutViewportScrollableArea()->ClampScrollOffset(
1132 history_item->GetScrollOffset()) == history_item->GetScrollOffset(); 1142 view_state->scroll_offset_) == view_state->scroll_offset_;
1133 1143
1134 bool should_force_clamping = 1144 bool should_force_clamping =
1135 !frame_->IsLoading() || history_load_type == kHistorySameDocumentLoad; 1145 !frame_->IsLoading() || history_load_type == kHistorySameDocumentLoad;
1136 // Here |can_restore_without_clamping| is false, but layout might be necessary 1146 // Here |can_restore_without_clamping| is false, but layout might be necessary
1137 // to ensure correct content size. 1147 // to ensure correct content size.
1138 if (!can_restore_without_clamping && should_force_clamping) 1148 if (!can_restore_without_clamping && should_force_clamping)
1139 frame_->GetDocument()->UpdateStyleAndLayout(); 1149 frame_->GetDocument()->UpdateStyleAndLayout();
1140 1150
1141 bool can_restore_without_annoying_user = 1151 bool can_restore_without_annoying_user =
1142 !GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user && 1152 !GetDocumentLoader()->GetInitialScrollState().was_scrolled_by_user &&
1143 (can_restore_without_clamping || should_force_clamping || 1153 (can_restore_without_clamping || should_force_clamping ||
1144 !should_restore_scroll); 1154 !should_restore_scroll);
1145 if (!can_restore_without_annoying_user) 1155 if (!can_restore_without_annoying_user)
1146 return; 1156 return;
1147 1157
1148 if (should_restore_scroll) { 1158 if (should_restore_scroll) {
1149 view->LayoutViewportScrollableArea()->SetScrollOffset( 1159 view->LayoutViewportScrollableArea()->SetScrollOffset(
1150 history_item->GetScrollOffset(), kProgrammaticScroll); 1160 view_state->scroll_offset_, kProgrammaticScroll);
1151 } 1161 }
1152 1162
1153 // For main frame restore scale and visual viewport position 1163 // For main frame restore scale and visual viewport position
1154 if (frame_->IsMainFrame()) { 1164 if (frame_->IsMainFrame()) {
1155 ScrollOffset visual_viewport_offset( 1165 ScrollOffset visual_viewport_offset(
1156 history_item->VisualViewportScrollOffset()); 1166 view_state->visual_viewport_scroll_offset_);
1157 1167
1158 // If the visual viewport's offset is (-1, -1) it means the history item 1168 // If the visual viewport's offset is (-1, -1) it means the history item
1159 // is an old version of HistoryItem so distribute the scroll between 1169 // is an old version of HistoryItem so distribute the scroll between
1160 // the main frame and the visual viewport as best as we can. 1170 // the main frame and the visual viewport as best as we can.
1161 if (visual_viewport_offset.Width() == -1 && 1171 if (visual_viewport_offset.Width() == -1 &&
1162 visual_viewport_offset.Height() == -1) { 1172 visual_viewport_offset.Height() == -1) {
1163 visual_viewport_offset = 1173 visual_viewport_offset =
1164 history_item->GetScrollOffset() - 1174 view_state->scroll_offset_ -
1165 view->LayoutViewportScrollableArea()->GetScrollOffset(); 1175 view->LayoutViewportScrollableArea()->GetScrollOffset();
1166 } 1176 }
1167 1177
1168 VisualViewport& visual_viewport = frame_->GetPage()->GetVisualViewport(); 1178 VisualViewport& visual_viewport = frame_->GetPage()->GetVisualViewport();
1169 if (should_restore_scale && should_restore_scroll) { 1179 if (should_restore_scale && should_restore_scroll) {
1170 visual_viewport.SetScaleAndLocation(history_item->PageScaleFactor(), 1180 visual_viewport.SetScaleAndLocation(view_state->page_scale_factor_,
1171 FloatPoint(visual_viewport_offset)); 1181 FloatPoint(visual_viewport_offset));
1172 } else if (should_restore_scale) { 1182 } else if (should_restore_scale) {
1173 visual_viewport.SetScale(history_item->PageScaleFactor()); 1183 visual_viewport.SetScale(view_state->page_scale_factor_);
1174 } else if (should_restore_scroll) { 1184 } else if (should_restore_scroll) {
1175 visual_viewport.SetLocation(FloatPoint(visual_viewport_offset)); 1185 visual_viewport.SetLocation(FloatPoint(visual_viewport_offset));
1176 } 1186 }
1177 1187
1178 if (ScrollingCoordinator* scrolling_coordinator = 1188 if (ScrollingCoordinator* scrolling_coordinator =
1179 frame_->GetPage()->GetScrollingCoordinator()) 1189 frame_->GetPage()->GetScrollingCoordinator())
1180 scrolling_coordinator->FrameViewRootLayerDidChange(view); 1190 scrolling_coordinator->FrameViewRootLayerDidChange(view);
1181 } 1191 }
1182 1192
1183 GetDocumentLoader()->GetInitialScrollState().did_restore_from_history = true; 1193 GetDocumentLoader()->GetInitialScrollState().did_restore_from_history = true;
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after
1743 // TODO(japhet): This is needed because the browser process DCHECKs if the 1753 // TODO(japhet): This is needed because the browser process DCHECKs if the
1744 // first entry we commit in a new frame has replacement set. It's unclear 1754 // first entry we commit in a new frame has replacement set. It's unclear
1745 // whether the DCHECK is right, investigate removing this special case. 1755 // whether the DCHECK is right, investigate removing this special case.
1746 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem && 1756 bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem &&
1747 (!Opener() || !request.Url().IsEmpty()); 1757 (!Opener() || !request.Url().IsEmpty());
1748 loader->SetReplacesCurrentHistoryItem(replace_current_item); 1758 loader->SetReplacesCurrentHistoryItem(replace_current_item);
1749 return loader; 1759 return loader;
1750 } 1760 }
1751 1761
1752 } // namespace blink 1762 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/loader/FrameLoader.h ('k') | third_party/WebKit/Source/core/loader/HistoryItem.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698