1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/web_view/navigation_controller.h"
7 #include "components/web_view/frame.h"
8 #include "components/web_view/navigation_controller_delegate.h"
9 #include "components/web_view/navigation_entry.h"
10 #include "components/web_view/reload_type.h"
14 NavigationController::NavigationController(
15 NavigationControllerDelegate
* delegate
)
16 : pending_entry_(nullptr),
17 last_committed_entry_index_(-1),
18 pending_entry_index_(-1),
19 delegate_(delegate
) {}
21 NavigationController::~NavigationController() {
22 DiscardPendingEntry(false);
25 int NavigationController::GetCurrentEntryIndex() const {
26 if (pending_entry_index_
!= -1)
27 return pending_entry_index_
;
28 return last_committed_entry_index_
;
31 int NavigationController::GetIndexForOffset(int offset
) const {
32 return GetCurrentEntryIndex() + offset
;
35 int NavigationController::GetEntryCount() const {
36 // TODO(erg): Have a max number of entries, and DCHECK that we are smaller
38 return static_cast<int>(entries_
.size());
41 NavigationEntry
* NavigationController::GetEntryAtIndex(int index
) const {
42 if (index
< 0 || index
>= GetEntryCount())
45 return entries_
[index
];
48 NavigationEntry
* NavigationController::GetEntryAtOffset(int offset
) const {
49 return GetEntryAtIndex(GetIndexForOffset(offset
));
52 bool NavigationController::CanGoBack() const {
53 return CanGoToOffset(-1);
56 bool NavigationController::CanGoForward() const {
57 return CanGoToOffset(1);
60 bool NavigationController::CanGoToOffset(int offset
) const {
61 int index
= GetIndexForOffset(offset
);
62 return index
>= 0 && index
< GetEntryCount();
65 void NavigationController::GoBack() {
71 // Base the navigation on where we are now...
72 int current_index
= GetCurrentEntryIndex();
74 DiscardPendingEntry(false);
76 pending_entry_index_
= current_index
- 1;
77 // TODO(erg): Transition type handled here.
78 NavigateToPendingEntry(ReloadType::NO_RELOAD
);
81 void NavigationController::GoForward() {
82 if (!CanGoForward()) {
87 // TODO(erg): The upstream version handles transience here.
89 // Base the navigation on where we are now...
90 int current_index
= GetCurrentEntryIndex();
92 DiscardPendingEntry(false);
94 pending_entry_index_
= current_index
+ 1;
95 // TODO(erg): Transition type handled here.
96 NavigateToPendingEntry(ReloadType::NO_RELOAD
);
99 void NavigationController::LoadURL(mojo::URLRequestPtr request
) {
100 // TODO(erg): This mimics part of NavigationControllerImpl::LoadURL(), minus
101 // all the error checking.
102 SetPendingEntry(make_scoped_ptr(new NavigationEntry(request
.Pass())));
103 NavigateToPendingEntry(ReloadType::NO_RELOAD
);
106 void NavigationController::NavigateToPendingEntry(ReloadType reload_type
) {
107 // TODO(erg): Deal with session history navigations while trying to navigate
108 // to a slow-to-commit page.
110 // TODO(erg): Deal with interstitials.
112 // For session history navigations only the pending_entry_index_ is set.
113 if (!pending_entry_
) {
114 CHECK_NE(pending_entry_index_
, -1);
115 pending_entry_
= entries_
[pending_entry_index_
];
118 // TODO(erg): Eventually, we need to deal with restoring the state of the
119 // full tree. For now, we'll just shell back to the WebView.
120 delegate_
->OnNavigate(pending_entry_
->BuildURLRequest());
123 void NavigationController::DiscardPendingEntry(bool was_failure
) {
124 // TODO(erg): We might copy the CHECK regarding NavigateToEntry here.
126 // TODO(erg): We need to maintain the failed_pending_entry_ during
127 // |was_failure| here.
129 if (pending_entry_index_
== -1)
130 delete pending_entry_
;
131 pending_entry_
= nullptr;
132 pending_entry_index_
= -1;
135 void NavigationController::SetPendingEntry(scoped_ptr
<NavigationEntry
> entry
) {
136 // TODO(erg): Should be DiscardNonCommittedEntries() if we start porting
137 // transient states over.
138 DiscardPendingEntry(false);
139 pending_entry_
= entry
.release();
140 DCHECK_EQ(-1, pending_entry_index_
);
141 // TODO(erg): The content code sends NOTIFICATION_NAV_ENTRY_PENDING here.
144 void NavigationController::FrameDidCommitProvisionalLoad(Frame
* frame
) {
145 // Our renderer is committing a frame. If this was a real implementation,
146 // we'd do something!
150 // TODO(erg): Need some equivalent of InsertOrReplaceEntry(), as we need to
151 // prune the history list.
153 // TODO(erg): We should copy all the logic from the various
154 // RendererDidNavigate* methods here.
156 // TODO(erg): Medium term, we shouldn't be reusing the NavigationEntry, as it
157 // appears that blink can change some of the data during the navigation. Do
158 // it for now for bootstrapping purposes.
159 if (pending_entry_index_
== -1 && pending_entry_
) {
160 int current_size
= static_cast<int>(entries_
.size());
161 if (current_size
> 0) {
162 while (last_committed_entry_index_
< (current_size
- 1)) {
168 entries_
.push_back(pending_entry_
);
169 last_committed_entry_index_
= static_cast<int>(entries_
.size() - 1);
170 pending_entry_
= nullptr;
171 } else if (pending_entry_index_
!= -1 && pending_entry_
) {
172 last_committed_entry_index_
= pending_entry_index_
;
173 pending_entry_
= nullptr;
175 // This was a historical navigation. In this limited prototype, we don't
176 // actually do anything with it.
179 << "Hit an unknown case in NavigationController::RendererDidNavigate";
182 DiscardPendingEntry(false);
184 delegate_
->OnDidNavigate();
187 } // namespace web_view