1// Copyright (c) 2012 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 "content/browser/web_contents/navigation_entry_impl.h"
6
7#include "base/metrics/histogram.h"
8#include "base/strings/string_util.h"
9#include "base/strings/utf_string_conversions.h"
10#include "content/public/common/content_constants.h"
11#include "content/public/common/url_constants.h"
12#include "net/base/net_util.h"
13#include "ui/base/text/text_elider.h"
14
15// Use this to get a new unique ID for a NavigationEntry during construction.
16// The returned ID is guaranteed to be nonzero (which is the "no ID" indicator).
17static int GetUniqueIDInConstructor() {
18  static int unique_id_counter = 0;
19  return ++unique_id_counter;
20}
21
22namespace content {
23
24int NavigationEntryImpl::kInvalidBindings = -1;
25
26NavigationEntry* NavigationEntry::Create() {
27  return new NavigationEntryImpl();
28}
29
30NavigationEntry* NavigationEntry::Create(const NavigationEntry& copy) {
31  return new NavigationEntryImpl(static_cast<const NavigationEntryImpl&>(copy));
32}
33
34NavigationEntryImpl* NavigationEntryImpl::FromNavigationEntry(
35    NavigationEntry* entry) {
36  return static_cast<NavigationEntryImpl*>(entry);
37}
38
39NavigationEntryImpl::NavigationEntryImpl()
40    : unique_id_(GetUniqueIDInConstructor()),
41      site_instance_(NULL),
42      bindings_(kInvalidBindings),
43      page_type_(PAGE_TYPE_NORMAL),
44      update_virtual_url_with_url_(false),
45      page_id_(-1),
46      transition_type_(PAGE_TRANSITION_LINK),
47      has_post_data_(false),
48      post_id_(-1),
49      restore_type_(RESTORE_NONE),
50      is_overriding_user_agent_(false),
51      is_renderer_initiated_(false),
52      should_replace_entry_(false),
53      should_clear_history_list_(false),
54      can_load_local_resources_(false) {
55}
56
57NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
58                                         int page_id,
59                                         const GURL& url,
60                                         const Referrer& referrer,
61                                         const string16& title,
62                                         PageTransition transition_type,
63                                         bool is_renderer_initiated)
64    : unique_id_(GetUniqueIDInConstructor()),
65      site_instance_(instance),
66      bindings_(kInvalidBindings),
67      page_type_(PAGE_TYPE_NORMAL),
68      url_(url),
69      referrer_(referrer),
70      update_virtual_url_with_url_(false),
71      title_(title),
72      page_id_(page_id),
73      transition_type_(transition_type),
74      has_post_data_(false),
75      post_id_(-1),
76      restore_type_(RESTORE_NONE),
77      is_overriding_user_agent_(false),
78      is_renderer_initiated_(is_renderer_initiated),
79      should_replace_entry_(false),
80      should_clear_history_list_(false),
81      can_load_local_resources_(false) {
82}
83
84NavigationEntryImpl::~NavigationEntryImpl() {
85}
86
87int NavigationEntryImpl::GetUniqueID() const {
88  return unique_id_;
89}
90
91PageType NavigationEntryImpl::GetPageType() const {
92  return page_type_;
93}
94
95void NavigationEntryImpl::SetURL(const GURL& url) {
96  url_ = url;
97  cached_display_title_.clear();
98}
99
100const GURL& NavigationEntryImpl::GetURL() const {
101  return url_;
102}
103
104void NavigationEntryImpl::SetBaseURLForDataURL(const GURL& url) {
105  base_url_for_data_url_ = url;
106}
107
108const GURL& NavigationEntryImpl::GetBaseURLForDataURL() const {
109  return base_url_for_data_url_;
110}
111
112void NavigationEntryImpl::SetReferrer(const Referrer& referrer) {
113  referrer_ = referrer;
114}
115
116const Referrer& NavigationEntryImpl::GetReferrer() const {
117  return referrer_;
118}
119
120void NavigationEntryImpl::SetVirtualURL(const GURL& url) {
121  virtual_url_ = (url == url_) ? GURL() : url;
122  cached_display_title_.clear();
123}
124
125const GURL& NavigationEntryImpl::GetVirtualURL() const {
126  return virtual_url_.is_empty() ? url_ : virtual_url_;
127}
128
129void NavigationEntryImpl::SetTitle(const string16& title) {
130  title_ = title;
131  cached_display_title_.clear();
132}
133
134const string16& NavigationEntryImpl::GetTitle() const {
135  return title_;
136}
137
138void NavigationEntryImpl::SetPageState(const PageState& state) {
139  page_state_ = state;
140}
141
142const PageState& NavigationEntryImpl::GetPageState() const {
143  return page_state_;
144}
145
146void NavigationEntryImpl::SetPageID(int page_id) {
147  page_id_ = page_id;
148}
149
150int32 NavigationEntryImpl::GetPageID() const {
151  return page_id_;
152}
153
154void NavigationEntryImpl::set_site_instance(SiteInstanceImpl* site_instance) {
155  site_instance_ = site_instance;
156}
157
158void NavigationEntryImpl::SetBindings(int bindings) {
159  // Ensure this is set to a valid value, and that it stays the same once set.
160  CHECK_NE(bindings, kInvalidBindings);
161  CHECK(bindings_ == kInvalidBindings || bindings_ == bindings);
162  bindings_ = bindings;
163}
164
165const string16& NavigationEntryImpl::GetTitleForDisplay(
166    const std::string& languages) const {
167  // Most pages have real titles. Don't even bother caching anything if this is
168  // the case.
169  if (!title_.empty())
170    return title_;
171
172  // More complicated cases will use the URLs as the title. This result we will
173  // cache since it's more complicated to compute.
174  if (!cached_display_title_.empty())
175    return cached_display_title_;
176
177  // Use the virtual URL first if any, and fall back on using the real URL.
178  string16 title;
179  if (!virtual_url_.is_empty()) {
180    title = net::FormatUrl(virtual_url_, languages);
181  } else if (!url_.is_empty()) {
182    title = net::FormatUrl(url_, languages);
183  }
184
185  // For file:// URLs use the filename as the title, not the full path.
186  if (url_.SchemeIsFile()) {
187    string16::size_type slashpos = title.rfind('/');
188    if (slashpos != string16::npos)
189      title = title.substr(slashpos + 1);
190  }
191
192  ui::ElideString(title, kMaxTitleChars, &cached_display_title_);
193  return cached_display_title_;
194}
195
196bool NavigationEntryImpl::IsViewSourceMode() const {
197  return virtual_url_.SchemeIs(kViewSourceScheme);
198}
199
200void NavigationEntryImpl::SetTransitionType(
201    PageTransition transition_type) {
202  transition_type_ = transition_type;
203}
204
205PageTransition NavigationEntryImpl::GetTransitionType() const {
206  return transition_type_;
207}
208
209const GURL& NavigationEntryImpl::GetUserTypedURL() const {
210  return user_typed_url_;
211}
212
213void NavigationEntryImpl::SetHasPostData(bool has_post_data) {
214  has_post_data_ = has_post_data;
215}
216
217bool NavigationEntryImpl::GetHasPostData() const {
218  return has_post_data_;
219}
220
221void NavigationEntryImpl::SetPostID(int64 post_id) {
222  post_id_ = post_id;
223}
224
225int64 NavigationEntryImpl::GetPostID() const {
226  return post_id_;
227}
228
229void NavigationEntryImpl::SetBrowserInitiatedPostData(
230    const base::RefCountedMemory* data) {
231  browser_initiated_post_data_ = data;
232}
233
234const base::RefCountedMemory*
235NavigationEntryImpl::GetBrowserInitiatedPostData() const {
236  return browser_initiated_post_data_.get();
237}
238
239
240const FaviconStatus& NavigationEntryImpl::GetFavicon() const {
241  return favicon_;
242}
243
244FaviconStatus& NavigationEntryImpl::GetFavicon() {
245  return favicon_;
246}
247
248const SSLStatus& NavigationEntryImpl::GetSSL() const {
249  return ssl_;
250}
251
252SSLStatus& NavigationEntryImpl::GetSSL() {
253  return ssl_;
254}
255
256void NavigationEntryImpl::SetOriginalRequestURL(const GURL& original_url) {
257  original_request_url_ = original_url;
258}
259
260const GURL& NavigationEntryImpl::GetOriginalRequestURL() const {
261  return original_request_url_;
262}
263
264void NavigationEntryImpl::SetIsOverridingUserAgent(bool override) {
265  is_overriding_user_agent_ = override;
266}
267
268bool NavigationEntryImpl::GetIsOverridingUserAgent() const {
269  return is_overriding_user_agent_;
270}
271
272void NavigationEntryImpl::SetTimestamp(base::Time timestamp) {
273  timestamp_ = timestamp;
274}
275
276base::Time NavigationEntryImpl::GetTimestamp() const {
277  return timestamp_;
278}
279
280void NavigationEntryImpl::SetCanLoadLocalResources(bool allow) {
281  can_load_local_resources_ = allow;
282}
283
284bool NavigationEntryImpl::GetCanLoadLocalResources() const {
285  return can_load_local_resources_;
286}
287
288void NavigationEntryImpl::SetFrameToNavigate(const std::string& frame_name) {
289  frame_to_navigate_ = frame_name;
290}
291
292const std::string& NavigationEntryImpl::GetFrameToNavigate() const {
293  return frame_to_navigate_;
294}
295
296void NavigationEntryImpl::SetExtraData(const std::string& key,
297                                       const string16& data) {
298  extra_data_[key] = data;
299}
300
301bool NavigationEntryImpl::GetExtraData(const std::string& key,
302                                       string16* data) const {
303  std::map<std::string, string16>::const_iterator iter = extra_data_.find(key);
304  if (iter == extra_data_.end())
305    return false;
306  *data = iter->second;
307  return true;
308}
309
310void NavigationEntryImpl::ClearExtraData(const std::string& key) {
311  extra_data_.erase(key);
312}
313
314void NavigationEntryImpl::SetScreenshotPNGData(
315    scoped_refptr<base::RefCountedBytes> png_data) {
316  screenshot_ = png_data;
317  if (screenshot_.get())
318    UMA_HISTOGRAM_MEMORY_KB("Overscroll.ScreenshotSize", screenshot_->size());
319}
320
321}  // namespace content
322