1 // Copyright 2014 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 "ios/web/navigation/navigation_item_impl.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "net/base/net_util.h"
10 #include "ui/base/page_transition_types.h"
11 #include "ui/gfx/text_elider.h"
15 // Returns a new unique ID for use in NavigationItem during construction. The
16 // returned ID is guaranteed to be nonzero (which is the "no ID" indicator).
17 static int GetUniqueIDInConstructor() {
18 static int unique_id_counter = 0;
19 return ++unique_id_counter;
27 scoped_ptr<NavigationItem> NavigationItem::Create() {
28 return scoped_ptr<NavigationItem>(new NavigationItemImpl());
31 NavigationItemImpl::NavigationItemImpl()
32 : unique_id_(GetUniqueIDInConstructor()),
33 transition_type_(ui::PAGE_TRANSITION_LINK),
34 is_overriding_user_agent_(false),
35 is_created_from_push_state_(false),
36 should_skip_resubmit_data_confirmation_(false),
37 is_renderer_initiated_(false),
39 facade_delegate_(nullptr) {
42 NavigationItemImpl::~NavigationItemImpl() {
45 NavigationItemImpl::NavigationItemImpl(const NavigationItemImpl& item)
46 : unique_id_(item.unique_id_),
48 referrer_(item.referrer_),
49 virtual_url_(item.virtual_url_),
51 page_display_state_(item.page_display_state_),
52 transition_type_(item.transition_type_),
53 favicon_(item.favicon_),
55 timestamp_(item.timestamp_),
56 is_overriding_user_agent_(item.is_overriding_user_agent_),
57 http_request_headers_([item.http_request_headers_ copy]),
58 serialized_state_object_([item.serialized_state_object_ copy]),
59 is_created_from_push_state_(item.is_created_from_push_state_),
60 should_skip_resubmit_data_confirmation_(
61 item.should_skip_resubmit_data_confirmation_),
62 post_data_([item.post_data_ copy]),
63 is_renderer_initiated_(item.is_renderer_initiated_),
64 is_unsafe_(item.is_unsafe_),
65 cached_display_title_(item.cached_display_title_),
66 facade_delegate_(nullptr) {
69 void NavigationItemImpl::SetFacadeDelegate(
70 scoped_ptr<NavigationItemFacadeDelegate> facade_delegate) {
71 facade_delegate_ = facade_delegate.Pass();
74 NavigationItemFacadeDelegate* NavigationItemImpl::GetFacadeDelegate() const {
75 return facade_delegate_.get();
78 int NavigationItemImpl::GetUniqueID() const {
82 void NavigationItemImpl::SetURL(const GURL& url) {
84 cached_display_title_.clear();
87 const GURL& NavigationItemImpl::GetURL() const {
91 void NavigationItemImpl::SetReferrer(const web::Referrer& referrer) {
95 const web::Referrer& NavigationItemImpl::GetReferrer() const {
99 void NavigationItemImpl::SetVirtualURL(const GURL& url) {
100 virtual_url_ = (url == url_) ? GURL() : url;
101 cached_display_title_.clear();
104 const GURL& NavigationItemImpl::GetVirtualURL() const {
105 return virtual_url_.is_empty() ? url_ : virtual_url_;
108 void NavigationItemImpl::SetTitle(const base::string16& title) {
110 cached_display_title_.clear();
113 const base::string16& NavigationItemImpl::GetTitle() const {
117 void NavigationItemImpl::SetPageDisplayState(
118 const web::PageDisplayState& display_state) {
119 page_display_state_ = display_state;
122 const PageDisplayState& NavigationItemImpl::GetPageDisplayState() const {
123 return page_display_state_;
126 const base::string16& NavigationItemImpl::GetTitleForDisplay(
127 const std::string& languages) const {
128 // Most pages have real titles. Don't even bother caching anything if this is
133 // More complicated cases will use the URLs as the title. This result we will
134 // cache since it's more complicated to compute.
135 if (!cached_display_title_.empty())
136 return cached_display_title_;
138 // Use the virtual URL first if any, and fall back on using the real URL.
139 base::string16 title;
140 if (!virtual_url_.is_empty()) {
141 title = net::FormatUrl(virtual_url_, languages);
142 } else if (!url_.is_empty()) {
143 title = net::FormatUrl(url_, languages);
146 // For file:// URLs use the filename as the title, not the full path.
147 if (url_.SchemeIsFile()) {
148 base::string16::size_type slashpos = title.rfind('/');
149 if (slashpos != base::string16::npos)
150 title = title.substr(slashpos + 1);
153 const int kMaxTitleChars = 4 * 1024;
154 gfx::ElideString(title, kMaxTitleChars, &cached_display_title_);
155 return cached_display_title_;
158 void NavigationItemImpl::SetTransitionType(ui::PageTransition transition_type) {
159 transition_type_ = transition_type;
162 ui::PageTransition NavigationItemImpl::GetTransitionType() const {
163 return transition_type_;
166 const FaviconStatus& NavigationItemImpl::GetFavicon() const {
170 FaviconStatus& NavigationItemImpl::GetFavicon() {
174 const SSLStatus& NavigationItemImpl::GetSSL() const {
178 SSLStatus& NavigationItemImpl::GetSSL() {
182 void NavigationItemImpl::SetTimestamp(base::Time timestamp) {
183 timestamp_ = timestamp;
186 base::Time NavigationItemImpl::GetTimestamp() const {
190 void NavigationItemImpl::SetUnsafe(bool is_unsafe) {
191 is_unsafe_ = is_unsafe;
194 bool NavigationItemImpl::IsUnsafe() const {
198 void NavigationItemImpl::SetIsOverridingUserAgent(
199 bool is_overriding_user_agent) {
200 is_overriding_user_agent_ = is_overriding_user_agent;
203 bool NavigationItemImpl::IsOverridingUserAgent() const {
204 return is_overriding_user_agent_;
207 bool NavigationItemImpl::HasPostData() const {
208 return post_data_.get() != nil;
211 NSDictionary* NavigationItemImpl::GetHttpRequestHeaders() const {
212 return [[http_request_headers_ copy] autorelease];
215 void NavigationItemImpl::AddHttpRequestHeaders(
216 NSDictionary* additional_headers) {
217 if (!additional_headers)
220 if (http_request_headers_)
221 [http_request_headers_ addEntriesFromDictionary:additional_headers];
223 http_request_headers_.reset([additional_headers mutableCopy]);
226 void NavigationItemImpl::SetSerializedStateObject(
227 NSString* serialized_state_object) {
228 serialized_state_object_.reset([serialized_state_object retain]);
231 NSString* NavigationItemImpl::GetSerializedStateObject() const {
232 return serialized_state_object_.get();
235 void NavigationItemImpl::SetIsCreatedFromPushState(bool push_state) {
236 is_created_from_push_state_ = push_state;
239 bool NavigationItemImpl::IsCreatedFromPushState() const {
240 return is_created_from_push_state_;
243 void NavigationItemImpl::SetShouldSkipResubmitDataConfirmation(bool skip) {
244 should_skip_resubmit_data_confirmation_ = skip;
247 bool NavigationItemImpl::ShouldSkipResubmitDataConfirmation() const {
248 return should_skip_resubmit_data_confirmation_;
251 void NavigationItemImpl::SetPostData(NSData* post_data) {
252 post_data_.reset([post_data retain]);
255 NSData* NavigationItemImpl::GetPostData() const {
256 return post_data_.get();
259 void NavigationItemImpl::RemoveHttpRequestHeaderForKey(NSString* key) {
261 [http_request_headers_ removeObjectForKey:key];
262 if (![http_request_headers_ count])
263 http_request_headers_.reset();
266 void NavigationItemImpl::ResetHttpRequestHeaders() {
267 http_request_headers_.reset();
270 void NavigationItemImpl::ResetForCommit() {
271 // Any state that only matters when a navigation item is pending should be
273 set_is_renderer_initiated(false);