OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "components/web_view/navigation_controller.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "components/web_view/frame.h" | |
10 #include "components/web_view/navigation_controller_delegate.h" | |
11 #include "components/web_view/navigation_entry.h" | |
12 #include "components/web_view/reload_type.h" | |
13 | |
14 namespace web_view { | |
15 | |
16 NavigationController::NavigationController( | |
17 NavigationControllerDelegate* delegate) | |
18 : pending_entry_(nullptr), | |
19 last_committed_entry_index_(-1), | |
20 pending_entry_index_(-1), | |
21 delegate_(delegate) {} | |
22 | |
23 NavigationController::~NavigationController() { | |
24 DiscardPendingEntry(false); | |
25 } | |
26 | |
27 int NavigationController::GetCurrentEntryIndex() const { | |
28 if (pending_entry_index_ != -1) | |
29 return pending_entry_index_; | |
30 return last_committed_entry_index_; | |
31 } | |
32 | |
33 int NavigationController::GetIndexForOffset(int offset) const { | |
34 return GetCurrentEntryIndex() + offset; | |
35 } | |
36 | |
37 int NavigationController::GetEntryCount() const { | |
38 // TODO(erg): Have a max number of entries, and DCHECK that we are smaller | |
39 // than it here. | |
40 return static_cast<int>(entries_.size()); | |
41 } | |
42 | |
43 NavigationEntry* NavigationController::GetEntryAtIndex(int index) const { | |
44 if (index < 0 || index >= GetEntryCount()) | |
45 return nullptr; | |
46 | |
47 return entries_[index]; | |
48 } | |
49 | |
50 NavigationEntry* NavigationController::GetEntryAtOffset(int offset) const { | |
51 return GetEntryAtIndex(GetIndexForOffset(offset)); | |
52 } | |
53 | |
54 bool NavigationController::CanGoBack() const { | |
55 return CanGoToOffset(-1); | |
56 } | |
57 | |
58 bool NavigationController::CanGoForward() const { | |
59 return CanGoToOffset(1); | |
60 } | |
61 | |
62 bool NavigationController::CanGoToOffset(int offset) const { | |
63 int index = GetIndexForOffset(offset); | |
64 return index >= 0 && index < GetEntryCount(); | |
65 } | |
66 | |
67 void NavigationController::GoBack() { | |
68 if (!CanGoBack()) { | |
69 NOTREACHED(); | |
70 return; | |
71 } | |
72 | |
73 // Base the navigation on where we are now... | |
74 int current_index = GetCurrentEntryIndex(); | |
75 | |
76 DiscardPendingEntry(false); | |
77 | |
78 pending_entry_index_ = current_index - 1; | |
79 // TODO(erg): Transition type handled here. | |
80 NavigateToPendingEntry(ReloadType::NO_RELOAD, true); | |
81 } | |
82 | |
83 void NavigationController::GoForward() { | |
84 if (!CanGoForward()) { | |
85 NOTREACHED(); | |
86 return; | |
87 } | |
88 | |
89 // TODO(erg): The upstream version handles transience here. | |
90 | |
91 // Base the navigation on where we are now... | |
92 int current_index = GetCurrentEntryIndex(); | |
93 | |
94 DiscardPendingEntry(false); | |
95 | |
96 pending_entry_index_ = current_index + 1; | |
97 // TODO(erg): Transition type handled here. | |
98 NavigateToPendingEntry(ReloadType::NO_RELOAD, true); | |
99 } | |
100 | |
101 void NavigationController::LoadURL(mojo::URLRequestPtr request) { | |
102 // TODO(erg): This mimics part of NavigationControllerImpl::LoadURL(), minus | |
103 // all the error checking. | |
104 SetPendingEntry(make_scoped_ptr(new NavigationEntry(std::move(request)))); | |
105 NavigateToPendingEntry(ReloadType::NO_RELOAD, false); | |
106 } | |
107 | |
108 void NavigationController::NavigateToPendingEntry( | |
109 ReloadType reload_type, | |
110 bool update_navigation_start_time) { | |
111 // TODO(erg): Deal with session history navigations while trying to navigate | |
112 // to a slow-to-commit page. | |
113 | |
114 // TODO(erg): Deal with interstitials. | |
115 | |
116 // For session history navigations only the pending_entry_index_ is set. | |
117 if (!pending_entry_) { | |
118 CHECK_NE(pending_entry_index_, -1); | |
119 pending_entry_ = entries_[pending_entry_index_]; | |
120 } | |
121 | |
122 // TODO(erg): Eventually, we need to deal with restoring the state of the | |
123 // full tree. For now, we'll just shell back to the WebView. | |
124 delegate_->OnNavigate( | |
125 pending_entry_->BuildURLRequest(update_navigation_start_time)); | |
126 } | |
127 | |
128 void NavigationController::DiscardPendingEntry(bool was_failure) { | |
129 // TODO(erg): We might copy the CHECK regarding NavigateToEntry here. | |
130 | |
131 // TODO(erg): We need to maintain the failed_pending_entry_ during | |
132 // |was_failure| here. | |
133 | |
134 if (pending_entry_index_ == -1) | |
135 delete pending_entry_; | |
136 pending_entry_ = nullptr; | |
137 pending_entry_index_ = -1; | |
138 } | |
139 | |
140 void NavigationController::SetPendingEntry(scoped_ptr<NavigationEntry> entry) { | |
141 // TODO(erg): Should be DiscardNonCommittedEntries() if we start porting | |
142 // transient states over. | |
143 DiscardPendingEntry(false); | |
144 pending_entry_ = entry.release(); | |
145 DCHECK_EQ(-1, pending_entry_index_); | |
146 // TODO(erg): The content code sends NOTIFICATION_NAV_ENTRY_PENDING here. | |
147 } | |
148 | |
149 void NavigationController::FrameDidCommitProvisionalLoad(Frame* frame) { | |
150 // Our renderer is committing a frame. If this was a real implementation, | |
151 // we'd do something! | |
152 if (frame->parent()) | |
153 return; | |
154 | |
155 // TODO(erg): Need some equivalent of InsertOrReplaceEntry(), as we need to | |
156 // prune the history list. | |
157 | |
158 // TODO(erg): We should copy all the logic from the various | |
159 // RendererDidNavigate* methods here. | |
160 | |
161 // TODO(erg): Medium term, we shouldn't be reusing the NavigationEntry, as it | |
162 // appears that blink can change some of the data during the navigation. Do | |
163 // it for now for bootstrapping purposes. | |
164 if (pending_entry_index_ == -1 && pending_entry_) { | |
165 ClearForwardEntries(); | |
166 entries_.push_back(pending_entry_); | |
167 last_committed_entry_index_ = static_cast<int>(entries_.size() - 1); | |
168 pending_entry_ = nullptr; | |
169 } else if (pending_entry_index_ != -1 && pending_entry_) { | |
170 last_committed_entry_index_ = pending_entry_index_; | |
171 pending_entry_ = nullptr; | |
172 | |
173 // This was a historical navigation. In this limited prototype, we don't | |
174 // actually do anything with it. | |
175 } else { | |
176 LOG(ERROR) | |
177 << "Hit an unknown case in NavigationController::RendererDidNavigate"; | |
178 } | |
179 | |
180 DiscardPendingEntry(false); | |
181 | |
182 delegate_->OnDidNavigate(); | |
183 } | |
184 | |
185 void NavigationController::FrameDidNavigateLocally(Frame* frame, | |
186 const GURL& url) { | |
187 // If this is a local navigation of a non-top frame, don't try to commit | |
188 // it. | |
189 if (frame->parent()) | |
190 return; | |
191 | |
192 ClearForwardEntries(); | |
193 | |
194 // TODO(erg): This is overly cheap handling of local navigations in | |
195 // frames. We don't have all the information needed to construct a real | |
196 // URLRequest. | |
197 | |
198 entries_.push_back(new NavigationEntry(url)); | |
199 last_committed_entry_index_ = static_cast<int>(entries_.size() - 1); | |
200 | |
201 delegate_->OnDidNavigate(); | |
202 } | |
203 | |
204 void NavigationController::ClearForwardEntries() { | |
205 int current_size = static_cast<int>(entries_.size()); | |
206 if (current_size > 0) { | |
207 while (last_committed_entry_index_ < (current_size - 1)) { | |
208 entries_.pop_back(); | |
209 current_size--; | |
210 } | |
211 } | |
212 } | |
213 | |
214 } // namespace web_view | |
OLD | NEW |