summaryrefslogtreecommitdiffstats
path: root/content/browser/frame_host/navigation_entry_impl.h
blob: 9fc75fc516d22515c17586cb604d317dd8785ca6 (plain)
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
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_IMPL_H_
#define CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_IMPL_H_

#include <stdint.h>

#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_vector.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/frame_host/frame_navigation_entry.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/frame_message_enums.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/common/page_state.h"
#include "content/public/common/ssl_status.h"

namespace content {
struct CommonNavigationParams;
struct RequestNavigationParams;
struct StartNavigationParams;

class CONTENT_EXPORT NavigationEntryImpl
    : public NON_EXPORTED_BASE(NavigationEntry) {
 public:
  // Represents a tree of FrameNavigationEntries that make up this joint session
  // history item.  The tree currently only tracks the main frame by default,
  // and is populated with subframe nodes in --site-per-process mode.
  struct TreeNode {
    TreeNode(FrameNavigationEntry* frame_entry);
    ~TreeNode();

    // Returns whether this TreeNode corresponds to |frame_tree_node|.
    bool MatchesFrame(FrameTreeNode* frame_tree_node) const;

    // Recursively makes a deep copy of TreeNode with copies of each of the
    // FrameNavigationEntries in the subtree.  Replaces the TreeNode
    // corresponding to |frame_tree_node| (and all of its children) with a new
    // TreeNode for |frame_navigation_entry|.  Pass nullptr for both parameters
    // to make a complete clone.
    // TODO(creis): For --site-per-process, share FrameNavigationEntries between
    // NavigationEntries of the same tab.
    scoped_ptr<TreeNode> CloneAndReplace(
        FrameTreeNode* frame_tree_node,
        FrameNavigationEntry* frame_navigation_entry) const;

    // Ref counted pointer that keeps the FrameNavigationEntry alive as long as
    // it is needed by this node's NavigationEntry.
    scoped_refptr<FrameNavigationEntry> frame_entry;

    // List of child TreeNodes, which will be deleted when this node is.
    ScopedVector<TreeNode> children;
  };

  static NavigationEntryImpl* FromNavigationEntry(NavigationEntry* entry);
  static const NavigationEntryImpl* FromNavigationEntry(
      const NavigationEntry* entry);
  static scoped_ptr<NavigationEntryImpl> FromNavigationEntry(
      scoped_ptr<NavigationEntry> entry);

  // The value of bindings() before it is set during commit.
  static int kInvalidBindings;

  NavigationEntryImpl();
  NavigationEntryImpl(SiteInstanceImpl* instance,
                      int page_id,
                      const GURL& url,
                      const Referrer& referrer,
                      const base::string16& title,
                      ui::PageTransition transition_type,
                      bool is_renderer_initiated);
  ~NavigationEntryImpl() override;

  // NavigationEntry implementation:
  int GetUniqueID() const override;
  PageType GetPageType() const override;
  void SetURL(const GURL& url) override;
  const GURL& GetURL() const override;
  void SetBaseURLForDataURL(const GURL& url) override;
  const GURL& GetBaseURLForDataURL() const override;
#if defined(OS_ANDROID)
  void SetDataURLAsString(
      scoped_refptr<base::RefCountedString> data_url) override;
  const scoped_refptr<const base::RefCountedString> GetDataURLAsString()
      const override;
#endif
  void SetReferrer(const Referrer& referrer) override;
  const Referrer& GetReferrer() const override;
  void SetVirtualURL(const GURL& url) override;
  const GURL& GetVirtualURL() const override;
  void SetTitle(const base::string16& title) override;
  const base::string16& GetTitle() const override;
  void SetPageState(const PageState& state) override;
  PageState GetPageState() const override;
  void SetPageID(int page_id) override;
  int32_t GetPageID() const override;
  const base::string16& GetTitleForDisplay(
      const std::string& languages) const override;
  bool IsViewSourceMode() const override;
  void SetTransitionType(ui::PageTransition transition_type) override;
  ui::PageTransition GetTransitionType() const override;
  const GURL& GetUserTypedURL() const override;
  void SetHasPostData(bool has_post_data) override;
  bool GetHasPostData() const override;
  void SetPostID(int64_t post_id) override;
  int64_t GetPostID() const override;
  void SetBrowserInitiatedPostData(const base::RefCountedMemory* data) override;
  const base::RefCountedMemory* GetBrowserInitiatedPostData() const override;
  const FaviconStatus& GetFavicon() const override;
  FaviconStatus& GetFavicon() override;
  const SSLStatus& GetSSL() const override;
  SSLStatus& GetSSL() override;
  void SetOriginalRequestURL(const GURL& original_url) override;
  const GURL& GetOriginalRequestURL() const override;
  void SetIsOverridingUserAgent(bool override) override;
  bool GetIsOverridingUserAgent() const override;
  void SetTimestamp(base::Time timestamp) override;
  base::Time GetTimestamp() const override;
  void SetCanLoadLocalResources(bool allow) override;
  bool GetCanLoadLocalResources() const override;
  void SetExtraData(const std::string& key,
                    const base::string16& data) override;
  bool GetExtraData(const std::string& key,
                    base::string16* data) const override;
  void ClearExtraData(const std::string& key) override;
  void SetHttpStatusCode(int http_status_code) override;
  int GetHttpStatusCode() const override;
  void SetRedirectChain(const std::vector<GURL>& redirects) override;
  const std::vector<GURL>& GetRedirectChain() const override;
  bool IsRestored() const override;

  // Creates a copy of this NavigationEntryImpl that can be modified
  // independently from the original.  Does not copy any value that would be
  // cleared in ResetForCommit.
  scoped_ptr<NavigationEntryImpl> Clone() const;

  // Like |Clone|, but replaces the FrameNavigationEntry corresponding to
  // |frame_tree_node| (and all its children) with |frame_entry|.
  // TODO(creis): Once we start sharing FrameNavigationEntries between
  // NavigationEntryImpls, we will need to support two versions of Clone: one
  // that shares the existing FrameNavigationEntries (for use within the same
  // tab) and one that draws them from a different pool (for use in a new tab).
  scoped_ptr<NavigationEntryImpl> CloneAndReplace(
      FrameTreeNode* frame_tree_node, FrameNavigationEntry* frame_entry) const;

  // Helper functions to construct NavigationParameters for a navigation to this
  // NavigationEntry.
  CommonNavigationParams ConstructCommonNavigationParams(
      const GURL& dest_url,
      const Referrer& dest_referrer,
      const FrameNavigationEntry& frame_entry,
      FrameMsg_Navigate_Type::Value navigation_type,
      LoFiState lofi_state,
      const base::TimeTicks& navigation_start) const;
  StartNavigationParams ConstructStartNavigationParams() const;
  RequestNavigationParams ConstructRequestNavigationParams(
      const FrameNavigationEntry& frame_entry,
      bool is_same_document_history_load,
      bool has_committed_real_load,
      bool intended_as_new_entry,
      int pending_offset_to_send,
      int current_offset_to_send,
      int current_length_to_send) const;

  // Once a navigation entry is committed, we should no longer track several
  // pieces of non-persisted state, as documented on the members below.
  void ResetForCommit();

  // Exposes the tree of FrameNavigationEntries that make up this joint session
  // history item.
  // In default Chrome, this tree only has a root node with an unshared
  // FrameNavigationEntry.  Subframes are only added to the tree if the
  // --site-per-process flag is passed.
  TreeNode* root_node() const {
    return frame_tree_.get();
  }

  // Finds the TreeNode associated with |frame_tree_node_id| to add or update
  // its FrameNavigationEntry.  A new FrameNavigationEntry is added if none
  // exists, or else the existing one (which might be shared with other
  // NavigationEntries) is updated with the given parameters.
  // Does nothing if there is no entry already and |url| is about:blank, since
  // that does not count as a real commit.
  void AddOrUpdateFrameEntry(FrameTreeNode* frame_tree_node,
                             const std::string& frame_unique_name,
                             int64_t item_sequence_number,
                             int64_t document_sequence_number,
                             SiteInstanceImpl* site_instance,
                             const GURL& url,
                             const Referrer& referrer,
                             const PageState& page_state);

  // Returns the FrameNavigationEntry corresponding to |frame_tree_node|, if
  // there is one in this NavigationEntry.
  FrameNavigationEntry* GetFrameEntry(FrameTreeNode* frame_tree_node) const;

  // Returns the FrameNavigationEntry corresponding to the frame with the given
  // |unique_name|, if any. This is useful when the FrameTreeNode cannot be used
  // to find the entry, such as for a newly created subframe in a history
  // navigation. Callers should update the FrameTreeNode ID of the entry so that
  // it can be found with |GetFrameEntry| above.
  // TODO(creis): Generate or verify the unique_name in the browser process.
  FrameNavigationEntry* GetFrameEntryByUniqueName(
      const std::string& unique_name) const;

  void set_unique_id(int unique_id) {
    unique_id_ = unique_id;
  }

  // The SiteInstance represents which pages must share processes. This is a
  // reference counted pointer to a shared SiteInstance.
  //
  // Note that the SiteInstance should usually not be changed after it is set,
  // but this may happen if the NavigationEntry was cloned and needs to use a
  // different SiteInstance.
  void set_site_instance(SiteInstanceImpl* site_instance);
  SiteInstanceImpl* site_instance() const {
    return frame_tree_->frame_entry->site_instance();
  }

  // The |source_site_instance| is used to identify the SiteInstance of the
  // frame that initiated the navigation.
  void set_source_site_instance(SiteInstanceImpl* source_site_instance);
  SiteInstanceImpl* source_site_instance() const {
    return source_site_instance_.get();
  }

  // Remember the set of bindings granted to this NavigationEntry 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.
  void SetBindings(int bindings);
  int bindings() const {
    return bindings_;
  }

  void set_page_type(PageType page_type) {
    page_type_ = page_type;
  }

  bool has_virtual_url() const {
    return !virtual_url_.is_empty();
  }

  bool update_virtual_url_with_url() const {
    return update_virtual_url_with_url_;
  }
  void set_update_virtual_url_with_url(bool update) {
    update_virtual_url_with_url_ = update;
  }

  // Extra headers (separated by \n) to send during the request.
  void set_extra_headers(const std::string& extra_headers) {
    extra_headers_ = extra_headers;
  }
  const std::string& extra_headers() const {
    return extra_headers_;
  }

  // Whether this (pending) navigation is renderer-initiated.  Resets to false
  // for all types of navigations after commit.
  void set_is_renderer_initiated(bool is_renderer_initiated) {
    is_renderer_initiated_ = is_renderer_initiated;
  }
  bool is_renderer_initiated() const {
    return is_renderer_initiated_;
  }

  void set_user_typed_url(const GURL& user_typed_url) {
    user_typed_url_ = user_typed_url;
  }

  // Enumerations of the possible restore types.
  enum RestoreType {
    // Restore from the previous session.
    RESTORE_LAST_SESSION_EXITED_CLEANLY,
    RESTORE_LAST_SESSION_CRASHED,

    // The entry has been restored from the current session. This is used when
    // the user issues 'reopen closed tab'.
    RESTORE_CURRENT_SESSION,

    // The entry was not restored.
    RESTORE_NONE
  };

  // The RestoreType for this entry. This is set if the entry was retored. This
  // is set to RESTORE_NONE once the entry is loaded.
  void set_restore_type(RestoreType type) {
    restore_type_ = type;
  }
  RestoreType restore_type() const {
    return restore_type_;
  }

  void set_transferred_global_request_id(
      const GlobalRequestID& transferred_global_request_id) {
    transferred_global_request_id_ = transferred_global_request_id;
  }

  GlobalRequestID transferred_global_request_id() const {
    return transferred_global_request_id_;
  }

  // Whether this (pending) navigation needs to replace current entry.
  // Resets to false after commit.
  bool should_replace_entry() const {
    return should_replace_entry_;
  }

  void set_should_replace_entry(bool should_replace_entry) {
    should_replace_entry_ = should_replace_entry;
  }

  void SetScreenshotPNGData(scoped_refptr<base::RefCountedBytes> png_data);
  const scoped_refptr<base::RefCountedBytes> screenshot() const {
    return screenshot_;
  }

  // Whether this (pending) navigation should clear the session history. Resets
  // to false after commit.
  bool should_clear_history_list() const {
    return should_clear_history_list_;
  }
  void set_should_clear_history_list(bool should_clear_history_list) {
    should_clear_history_list_ = should_clear_history_list;
  }

  // Indicates which FrameTreeNode to navigate.  Currently only used if the
  // --site-per-process flag is passed.
  int frame_tree_node_id() const {
    return frame_tree_node_id_;
  }
  void set_frame_tree_node_id(int frame_tree_node_id) {
    frame_tree_node_id_ = frame_tree_node_id;
  }

  // Returns the history URL for a data URL to use in Blink.
  GURL GetHistoryURLForDataURL() const;

#if defined(OS_ANDROID)
  base::TimeTicks intent_received_timestamp() const {
    return intent_received_timestamp_;
  }

  void set_intent_received_timestamp(
      const base::TimeTicks intent_received_timestamp) {
    intent_received_timestamp_ = intent_received_timestamp;
  }

  bool has_user_gesture() const {
    return has_user_gesture_;
  }

  void set_has_user_gesture (bool has_user_gesture) {
    has_user_gesture_ = has_user_gesture;
  }
#endif

 private:
  // Finds the TreeNode associated with |frame_tree_node|, if any.
  NavigationEntryImpl::TreeNode* FindFrameEntry(
      FrameTreeNode* frame_tree_node) const;

  // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  // Session/Tab restore save portions of this class so that it can be recreated
  // later. If you add a new field that needs to be persisted you'll have to
  // update SessionService/TabRestoreService and Android WebView
  // state_serializer.cc appropriately.
  // For all new fields, update |Clone| and possibly |ResetForCommit|.
  // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING

  // Tree of FrameNavigationEntries, one for each frame on the page.
  // TODO(creis): Once FrameNavigationEntries can be shared across multiple
  // NavigationEntries, we will need to update Session/Tab restore.  For now,
  // each NavigationEntry's tree has its own unshared FrameNavigationEntries.
  scoped_ptr<TreeNode> frame_tree_;

  // See the accessors above for descriptions.
  int unique_id_;
  // TODO(creis): Persist bindings_. http://crbug.com/173672.
  int bindings_;
  PageType page_type_;
  GURL virtual_url_;
  bool update_virtual_url_with_url_;
  base::string16 title_;
  FaviconStatus favicon_;
  int32_t page_id_;
  SSLStatus ssl_;
  ui::PageTransition transition_type_;
  GURL user_typed_url_;
  bool has_post_data_;
  int64_t post_id_;
  RestoreType restore_type_;
  GURL original_request_url_;
  bool is_overriding_user_agent_;
  base::Time timestamp_;
  int http_status_code_;

  // This member is not persisted with session restore because it is transient.
  // If the post request succeeds, this field is cleared since the same
  // information is stored in |content_state_| above. It is also only shallow
  // copied with compiler provided copy constructor.
  // Cleared in |ResetForCommit|.
  scoped_refptr<const base::RefCountedMemory> browser_initiated_post_data_;

  // This is also a transient member (i.e. is not persisted with session
  // restore). The screenshot of a page is taken when navigating away from the
  // page. This screenshot is displayed during an overscroll-navigation
  // gesture. |screenshot_| will be NULL when the screenshot is not available
  // (e.g. after a session restore, or if taking the screenshot of a page
  // failed). The UI is responsible for dealing with missing screenshots
  // appropriately (e.g. display a placeholder image instead).
  scoped_refptr<base::RefCountedBytes> screenshot_;

  // This member is not persisted with session restore.
  std::string extra_headers_;

  // This member is cleared in |ResetForCommit| and not persisted.
  scoped_refptr<SiteInstanceImpl> source_site_instance_;

  // Used for specifying base URL for pages loaded via data URLs. Only used and
  // persisted by Android WebView.
  GURL base_url_for_data_url_;

#if defined(OS_ANDROID)
  // Used for passing really big data URLs from browser to renderers. Only used
  // and persisted by Android WebView.
  scoped_refptr<const base::RefCountedString> data_url_as_string_;
#endif

  // Whether the entry, while loading, was created for a renderer-initiated
  // navigation.  This dictates whether the URL should be displayed before the
  // navigation commits.  It is cleared in |ResetForCommit| and not persisted.
  bool is_renderer_initiated_;

  // This is a cached version of the result of GetTitleForDisplay. It prevents
  // us from having to do URL formatting on the URL every time the title is
  // displayed. When the URL, virtual URL, or title is set, this should be
  // cleared to force a refresh.
  mutable base::string16 cached_display_title_;

  // In case a navigation is transferred to a new RVH but the request has
  // been generated in the renderer already, this identifies the old request so
  // that it can be resumed. The old request is stored until the
  // ResourceDispatcher receives the navigation from the renderer which
  // carries this |transferred_global_request_id_| annotation. Once the request
  // is transferred to the new process, this is cleared and the request
  // continues as normal.
  // Cleared in |ResetForCommit|.
  GlobalRequestID transferred_global_request_id_;

  // This is set to true when this entry is being reloaded and due to changes in
  // the state of the URL, it has to be reloaded in a different site instance.
  // In such case, we must treat it as an existing navigation in the new site
  // instance, instead of a new navigation. This value should not be persisted
  // and is cleared in |ResetForCommit|.
  //
  // We also use this flag for cross-process redirect navigations, so that the
  // browser will replace the current navigation entry (which is the page
  // doing the redirect).
  bool should_replace_entry_;

  // This is used when transferring a pending entry from one process to another.
  // We also send this data through session sync for offline analysis.
  // It is preserved after commit but should not be persisted.
  std::vector<GURL> redirect_chain_;

  // This is set to true when this entry's navigation should clear the session
  // history both on the renderer and browser side. The browser side history
  // won't be cleared until the renderer has committed this navigation. This
  // entry is not persisted by the session restore system, as it is always
  // cleared in |ResetForCommit|.
  bool should_clear_history_list_;

  // Set when this entry should be able to access local file:// resources. This
  // value is not needed after the entry commits and is not persisted.
  bool can_load_local_resources_;

  // If not -1, this indicates which FrameTreeNode to navigate.  This field is
  // not persisted because it is experimental and only used when the
  // --site-per-process flag is passed.  It is cleared in |ResetForCommit|
  // because we only use it while the navigation is pending.
  // TODO(creis): Move this to FrameNavigationEntry.
  int frame_tree_node_id_;

#if defined(OS_ANDROID)
  // The time at which Chrome received the Android Intent that triggered this
  // URL load operation. Reset at commit and not persisted.
  base::TimeTicks intent_received_timestamp_;

  // Whether the URL load carries a user gesture.
  bool has_user_gesture_;
#endif

  // Used to store extra data to support browser features. This member is not
  // persisted, unless specific data is taken out/put back in at save/restore
  // time (see TabNavigation for an example of this).
  std::map<std::string, base::string16> extra_data_;

  DISALLOW_COPY_AND_ASSIGN(NavigationEntryImpl);
};

}  // namespace content

#endif  // CONTENT_BROWSER_FRAME_HOST_NAVIGATION_ENTRY_IMPL_H_