[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / frame_host / navigation_request.cc
bloba99074f2ce3aeb56440b44cc0e9530f0f0c1db39
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 "content/browser/frame_host/navigation_request.h"
7 #include "content/browser/frame_host/frame_tree.h"
8 #include "content/browser/frame_host/frame_tree_node.h"
9 #include "content/browser/frame_host/navigation_controller_impl.h"
10 #include "content/browser/frame_host/navigation_handle_impl.h"
11 #include "content/browser/frame_host/navigation_request_info.h"
12 #include "content/browser/frame_host/navigator.h"
13 #include "content/browser/loader/navigation_url_loader.h"
14 #include "content/browser/site_instance_impl.h"
15 #include "content/common/resource_request_body.h"
16 #include "content/public/browser/navigation_controller.h"
17 #include "content/public/browser/stream_handle.h"
18 #include "content/public/common/content_client.h"
19 #include "net/base/load_flags.h"
20 #include "net/http/http_request_headers.h"
21 #include "net/url_request/redirect_info.h"
23 namespace content {
25 namespace {
27 // Returns the net load flags to use based on the navigation type.
28 // TODO(clamy): unify the code with what is happening on the renderer side.
29 int LoadFlagFromNavigationType(FrameMsg_Navigate_Type::Value navigation_type) {
30 int load_flags = net::LOAD_NORMAL;
31 switch (navigation_type) {
32 case FrameMsg_Navigate_Type::RELOAD:
33 case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
34 load_flags |= net::LOAD_VALIDATE_CACHE;
35 break;
36 case FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE:
37 load_flags |= net::LOAD_BYPASS_CACHE;
38 break;
39 case FrameMsg_Navigate_Type::RESTORE:
40 load_flags |= net::LOAD_PREFERRING_CACHE;
41 break;
42 case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
43 load_flags |= net::LOAD_ONLY_FROM_CACHE;
44 break;
45 case FrameMsg_Navigate_Type::NORMAL:
46 default:
47 break;
49 return load_flags;
52 } // namespace
54 // static
55 scoped_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
56 FrameTreeNode* frame_tree_node,
57 const GURL& dest_url,
58 const Referrer& dest_referrer,
59 const FrameNavigationEntry& frame_entry,
60 const NavigationEntryImpl& entry,
61 FrameMsg_Navigate_Type::Value navigation_type,
62 bool is_same_document_history_load,
63 base::TimeTicks navigation_start,
64 NavigationControllerImpl* controller) {
65 std::string method = entry.GetHasPostData() ? "POST" : "GET";
67 // Copy existing headers and add necessary headers that may not be present
68 // in the RequestNavigationParams.
69 net::HttpRequestHeaders headers;
70 headers.AddHeadersFromString(entry.extra_headers());
71 headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
72 GetContentClient()->GetUserAgent());
73 // TODO(clamy): match what blink is doing with accept headers.
74 headers.SetHeaderIfMissing("Accept", "*/*");
76 // Fill POST data from the browser in the request body.
77 scoped_refptr<ResourceRequestBody> request_body;
78 if (entry.GetHasPostData()) {
79 request_body = new ResourceRequestBody();
80 request_body->AppendBytes(
81 reinterpret_cast<const char *>(
82 entry.GetBrowserInitiatedPostData()->front()),
83 entry.GetBrowserInitiatedPostData()->size());
86 scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest(
87 frame_tree_node,
88 entry.ConstructCommonNavigationParams(dest_url, dest_referrer,
89 frame_entry, navigation_type),
90 BeginNavigationParams(method, headers.ToString(),
91 LoadFlagFromNavigationType(navigation_type), false),
92 entry.ConstructRequestNavigationParams(
93 frame_entry, navigation_start, is_same_document_history_load,
94 frame_tree_node->has_committed_real_load(),
95 controller->GetPendingEntryIndex() == -1,
96 controller->GetIndexOfEntry(&entry),
97 controller->GetLastCommittedEntryIndex(),
98 controller->GetEntryCount()),
99 request_body, true, &frame_entry, &entry));
100 return navigation_request.Pass();
103 // static
104 scoped_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
105 FrameTreeNode* frame_tree_node,
106 const CommonNavigationParams& common_params,
107 const BeginNavigationParams& begin_params,
108 scoped_refptr<ResourceRequestBody> body,
109 int current_history_list_offset,
110 int current_history_list_length) {
111 // TODO(clamy): Check if some PageState should be provided here.
112 // TODO(clamy): See how we should handle override of the user agent when the
113 // navigation may start in a renderer and commit in another one.
114 // TODO(clamy): See if the navigation start time should be measured in the
115 // renderer and sent to the browser instead of being measured here.
116 // TODO(clamy): The pending history list offset should be properly set.
117 // TODO(clamy): Set has_committed_real_load.
118 RequestNavigationParams request_params;
119 request_params.current_history_list_offset = current_history_list_offset;
120 request_params.current_history_list_length = current_history_list_length;
121 scoped_ptr<NavigationRequest> navigation_request(
122 new NavigationRequest(frame_tree_node, common_params, begin_params,
123 request_params, body, false, nullptr, nullptr));
124 return navigation_request.Pass();
127 NavigationRequest::NavigationRequest(
128 FrameTreeNode* frame_tree_node,
129 const CommonNavigationParams& common_params,
130 const BeginNavigationParams& begin_params,
131 const RequestNavigationParams& request_params,
132 scoped_refptr<ResourceRequestBody> body,
133 bool browser_initiated,
134 const FrameNavigationEntry* frame_entry,
135 const NavigationEntryImpl* entry)
136 : frame_tree_node_(frame_tree_node),
137 common_params_(common_params),
138 begin_params_(begin_params),
139 request_params_(request_params),
140 browser_initiated_(browser_initiated),
141 state_(NOT_STARTED),
142 restore_type_(NavigationEntryImpl::RESTORE_NONE),
143 is_view_source_(false),
144 bindings_(NavigationEntryImpl::kInvalidBindings) {
145 DCHECK_IMPLIES(browser_initiated, entry != nullptr && frame_entry != nullptr);
146 if (browser_initiated) {
147 // TODO(clamy): use the FrameNavigationEntry for the source SiteInstance
148 // once it has been moved from the NavigationEntry.
149 source_site_instance_ = entry->source_site_instance();
150 dest_site_instance_ = frame_entry->site_instance();
151 restore_type_ = entry->restore_type();
152 is_view_source_ = entry->IsViewSourceMode();
153 bindings_ = entry->bindings();
154 } else {
155 // This is needed to have about:blank and data URLs commit in the same
156 // SiteInstance as the initiating renderer.
157 source_site_instance_ =
158 frame_tree_node->current_frame_host()->GetSiteInstance();
161 const GURL& first_party_for_cookies =
162 frame_tree_node->IsMainFrame()
163 ? common_params.url
164 : frame_tree_node->frame_tree()->root()->current_url();
165 bool parent_is_main_frame = !frame_tree_node->parent() ?
166 false : frame_tree_node->parent()->IsMainFrame();
167 info_.reset(new NavigationRequestInfo(
168 common_params, begin_params, first_party_for_cookies,
169 frame_tree_node->IsMainFrame(), parent_is_main_frame,
170 frame_tree_node->frame_tree_node_id(), body));
173 NavigationRequest::~NavigationRequest() {
176 bool NavigationRequest::BeginNavigation() {
177 DCHECK(!loader_);
178 DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE);
179 state_ = STARTED;
181 if (ShouldMakeNetworkRequestForURL(common_params_.url)) {
182 loader_ = NavigationURLLoader::Create(
183 frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
184 frame_tree_node_->frame_tree_node_id(), info_.Pass(), this);
185 return true;
188 // There is no need to make a network request for this navigation, so commit
189 // it immediately.
190 state_ = RESPONSE_STARTED;
191 frame_tree_node_->navigator()->CommitNavigation(
192 frame_tree_node_, nullptr, scoped_ptr<StreamHandle>());
193 return false;
195 // TODO(davidben): Fire (and add as necessary) observer methods such as
196 // DidStartProvisionalLoadForFrame for the navigation.
199 void NavigationRequest::CreateNavigationHandle(NavigatorDelegate* delegate) {
200 navigation_handle_ = NavigationHandleImpl::Create(
201 common_params_.url, frame_tree_node_->IsMainFrame(), delegate);
204 void NavigationRequest::TransferNavigationHandleOwnership(
205 RenderFrameHostImpl* render_frame_host) {
206 render_frame_host->SetNavigationHandle(navigation_handle_.Pass());
209 void NavigationRequest::OnRequestRedirected(
210 const net::RedirectInfo& redirect_info,
211 const scoped_refptr<ResourceResponse>& response) {
212 // TODO(davidben): Track other changes from redirects. These are important
213 // for, e.g., reloads.
214 common_params_.url = redirect_info.new_url;
216 // TODO(davidben): This where prerender and navigation_interceptor should be
217 // integrated. For now, just always follow all redirects.
218 loader_->FollowRedirect();
220 navigation_handle_->DidRedirectNavigation(redirect_info.new_url);
223 void NavigationRequest::OnResponseStarted(
224 const scoped_refptr<ResourceResponse>& response,
225 scoped_ptr<StreamHandle> body) {
226 DCHECK(state_ == STARTED);
227 state_ = RESPONSE_STARTED;
228 frame_tree_node_->navigator()->CommitNavigation(frame_tree_node_,
229 response.get(), body.Pass());
232 void NavigationRequest::OnRequestFailed(bool has_stale_copy_in_cache,
233 int net_error) {
234 DCHECK(state_ == STARTED);
235 state_ = FAILED;
236 navigation_handle_->set_net_error_code(static_cast<net::Error>(net_error));
237 frame_tree_node_->navigator()->FailedNavigation(
238 frame_tree_node_, has_stale_copy_in_cache, net_error);
241 void NavigationRequest::OnRequestStarted(base::TimeTicks timestamp) {
242 frame_tree_node_->navigator()->LogResourceRequestTime(timestamp,
243 common_params_.url);
246 } // namespace content