1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
content / browser / renderer_host / frame_navigation_entry.h [blame]
// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_
#define CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_
#include <stdint.h>
#include <optional>
#include "base/memory/ref_counted.h"
#include "content/browser/renderer_host/policy_container_host.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_export.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/referrer.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/page_state/page_state.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace network {
class ResourceRequestBody;
}
namespace content {
// Represents a session history item for a particular frame. It is matched with
// corresponding FrameTreeNodes using unique name (or by the root position).
// There is a tree of FrameNavigationEntries in each NavigationEntry, one per
// frame.
//
// This class is refcounted and can be shared across multiple NavigationEntries.
// Each RenderFrameHost also keeps a scoped_refptr to its last committed
// FrameNavigationEntry, to accurately track its current state in cases when the
// last committed NavigationEntry may not match (e.g., when missing the
// relevant FrameNavigationEntry or during a history navigation targeting
// multiple frames while only some have committed.)
class CONTENT_EXPORT FrameNavigationEntry
: public base::RefCounted<FrameNavigationEntry> {
public:
FrameNavigationEntry(
const std::string& frame_unique_name,
int64_t item_sequence_number,
int64_t document_sequence_number,
const std::string& navigation_api_key,
scoped_refptr<SiteInstanceImpl> site_instance,
scoped_refptr<SiteInstanceImpl> source_site_instance,
const GURL& url,
const std::optional<url::Origin>& origin,
const Referrer& referrer,
const std::optional<url::Origin>& initiator_origin,
const std::optional<GURL>& initiator_base_url,
const std::vector<GURL>& redirect_chain,
const blink::PageState& page_state,
const std::string& method,
int64_t post_id,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
std::unique_ptr<PolicyContainerPolicies> policy_container_policies,
bool protect_url_in_navigation_api);
FrameNavigationEntry(const FrameNavigationEntry&) = delete;
FrameNavigationEntry& operator=(const FrameNavigationEntry&) = delete;
// Creates a copy of this FrameNavigationEntry that can be modified
// independently from the original.
scoped_refptr<FrameNavigationEntry> Clone() const;
// Updates all the members of this entry.
void UpdateEntry(
const std::string& frame_unique_name,
int64_t item_sequence_number,
int64_t document_sequence_number,
const std::string& navigation_api_key,
SiteInstanceImpl* site_instance,
scoped_refptr<SiteInstanceImpl> source_site_instance,
const GURL& url,
const std::optional<url::Origin>& origin,
const Referrer& referrer,
const std::optional<url::Origin>& initiator_origin,
const std::optional<GURL>& initiator_base_url,
const std::vector<GURL>& redirect_chain,
const blink::PageState& page_state,
const std::string& method,
int64_t post_id,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
std::unique_ptr<PolicyContainerPolicies> policy_container_policies,
bool protect_url_in_navigation_api);
// The unique name of the frame this entry is for. This is a stable name for
// the frame based on its position in the tree and relation to other named
// frames, which does not change after cross-process navigations or restores.
// Only the main frame can have an empty name.
//
// This is unique relative to other frames in the same page, but not among
// other pages (i.e., not globally unique).
const std::string& frame_unique_name() const { return frame_unique_name_; }
void set_frame_unique_name(const std::string& frame_unique_name) {
frame_unique_name_ = frame_unique_name;
}
// Keeps track of where this entry belongs in the frame's session history.
// The item sequence number identifies each stop in the back/forward history
// and is globally unique. The document sequence number increments for each
// new document and is also globally unique. In-page navigations get a new
// item sequence number but the same document sequence number. These numbers
// should not change once assigned.
void set_item_sequence_number(int64_t item_sequence_number);
int64_t item_sequence_number() const { return item_sequence_number_; }
void set_document_sequence_number(int64_t document_sequence_number);
int64_t document_sequence_number() const { return document_sequence_number_; }
// Identifies a "slot" in the frame's session history for the
// window.navigation API.
void set_navigation_api_key(const std::string& navigation_api_key);
const std::string& navigation_api_key() const { return navigation_api_key_; }
// The SiteInstance, as assigned at commit time, responsible for rendering
// this frame. All frames sharing a SiteInstance must live in the same
// process. This is a refcounted pointer that keeps the SiteInstance (not
// necessarily the process) alive as long as this object remains in the
// session history.
SiteInstanceImpl* site_instance() const { return site_instance_.get(); }
// The |source_site_instance| is used to identify the SiteInstance of the
// frame that initiated the navigation. It is present only for
// renderer-initiated navigations and is cleared once the navigation has
// committed.
void set_source_site_instance(
scoped_refptr<SiteInstanceImpl> source_site_instance) {
source_site_instance_ = std::move(source_site_instance);
}
SiteInstanceImpl* source_site_instance() const {
return source_site_instance_.get();
}
// The actual URL loaded in the frame. This is in contrast to the virtual
// URL, which is shown to the user.
void set_url(const GURL& url) { url_ = url; }
const GURL& url() const { return url_; }
// The referring URL. Can be empty.
void set_referrer(const Referrer& referrer) { referrer_ = referrer; }
const Referrer& referrer() const { return referrer_; }
// The origin that initiated the original navigation. std::nullopt means
// that the original navigation was browser-initiated (e.g. initiated from a
// trusted surface like the omnibox or the bookmarks bar).
const std::optional<url::Origin>& initiator_origin() const {
return initiator_origin_;
}
// The base url of the initiator of the navigation. This is only set if the
// url is about:blank or about:srcdoc.
const std::optional<GURL>& initiator_base_url() const {
return initiator_base_url_;
}
// The origin of the document the frame has committed. It is optional, since
// pending entries do not have an origin associated with them and the real
// origin is set at commit time.
void set_committed_origin(const url::Origin& origin) {
committed_origin_ = origin;
}
const std::optional<url::Origin>& committed_origin() const {
return committed_origin_;
}
// The redirect chain traversed during this frame navigation, from the initial
// redirecting URL to the final non-redirecting current URL.
void set_redirect_chain(const std::vector<GURL>& redirect_chain) {
redirect_chain_ = redirect_chain;
}
const std::vector<GURL>& redirect_chain() const { return redirect_chain_; }
void SetPageState(const blink::PageState& page_state);
const blink::PageState& page_state() const { return page_state_; }
// Remember the set of bindings granted to this FrameNavigationEntry at the
// time of commit, to ensure that we do not grant it additional bindings if we
// navigate back to it in the future. This can only be changed once.
// bindings() will return nullopt before the bindings are set.
void SetBindings(BindingsPolicySet bindings);
std::optional<BindingsPolicySet> bindings() const { return bindings_; }
// The HTTP method used to navigate.
const std::string& method() const { return method_; }
void set_method(const std::string& method) { method_ = method; }
// Returns true if the HTTP method was POST.
bool get_has_post_data() { return method() == "POST"; }
// The id of the post corresponding to this navigation or -1 if the
// navigation was not a POST.
int64_t post_id() const { return post_id_; }
void set_post_id(int64_t post_id) { post_id_ = post_id; }
// The data sent during a POST navigation. Returns nullptr if the navigation
// is not a POST.
scoped_refptr<network::ResourceRequestBody> GetPostData(
std::string* content_type) const;
// The policy container policies for this entry. This is needed for local
// schemes, since for them the policy container was inherited by the creator,
// while for network schemes we can reconstruct the policy container by
// parsing the network response.
void set_policy_container_policies(
std::unique_ptr<PolicyContainerPolicies> policies) {
policy_container_policies_ = std::move(policies);
}
const PolicyContainerPolicies* policy_container_policies() const {
return policy_container_policies_.get();
}
// Optional URLLoaderFactory to facilitate blob URL loading.
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory()
const {
return blob_url_loader_factory_;
}
void set_blob_url_loader_factory(
scoped_refptr<network::SharedURLLoaderFactory> factory) {
blob_url_loader_factory_ = std::move(factory);
}
bool protect_url_in_navigation_api() {
return protect_url_in_navigation_api_;
}
void set_protect_url_in_navigation_api(bool protect) {
protect_url_in_navigation_api_ = protect;
}
private:
friend class base::RefCounted<FrameNavigationEntry>;
virtual ~FrameNavigationEntry();
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
// Add all new fields to |UpdateEntry|.
// TODO(creis): These fields have implications for session restore. This is
// currently managed by NavigationEntry, but the logic will move here.
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
// See the accessors above for descriptions.
std::string frame_unique_name_;
// sequence numbers and the navigation API key are also stored in
// |page_state_|. When SetPageState() is called as part of a restore, it also
// initializes these.
int64_t item_sequence_number_;
int64_t document_sequence_number_;
std::string navigation_api_key_;
// TODO(nasko, creis): The SiteInstance of a FrameNavigationEntry should
// not change once it has been assigned. See https://crbug.com/849430.
scoped_refptr<SiteInstanceImpl> site_instance_;
// This member is cleared at commit time and is not persisted.
scoped_refptr<SiteInstanceImpl> source_site_instance_;
GURL url_;
// For a committed navigation, holds the origin of the resulting document.
// TODO(nasko): This should be possible to calculate at ReadyToCommit time
// and verified when receiving the DidCommit IPC.
std::optional<url::Origin> committed_origin_;
Referrer referrer_;
std::optional<url::Origin> initiator_origin_;
std::optional<GURL> initiator_base_url_;
// This is used when transferring a pending entry from one process to another.
// We also send the main frame's redirect chain through session sync for
// offline analysis.
// It is preserved after commit but should not be persisted.
std::vector<GURL> redirect_chain_;
// TODO(creis): Change this to FrameState.
blink::PageState page_state_;
// TODO(creis): Persist bindings_. https://crbug.com/40076915.
std::optional<BindingsPolicySet> bindings_;
std::string method_;
int64_t post_id_;
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_;
// TODO(crbug.com/40053667): Persist these policies.
std::unique_ptr<PolicyContainerPolicies> policy_container_policies_;
// If the document represented by this FNE hid its full url from appearing
// in a referrer via a "no-referrer" or "origin" referrer policy, this URL
// will be hidden from navigation API history entries as well.
bool protect_url_in_navigation_api_;
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_