Add remoting and PPAPI tests to GN build
[chromium-blink-merge.git] / content / browser / frame_host / navigation_request.cc
blob75e61001c501bc9a5320b5e493187b67c4437afa
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_request_info.h"
10 #include "content/browser/frame_host/navigator.h"
11 #include "content/browser/loader/navigation_url_loader.h"
12 #include "content/browser/site_instance_impl.h"
13 #include "content/common/resource_request_body.h"
14 #include "content/public/browser/navigation_controller.h"
15 #include "content/public/browser/stream_handle.h"
16 #include "content/public/common/content_client.h"
17 #include "net/base/load_flags.h"
18 #include "net/http/http_request_headers.h"
19 #include "net/url_request/redirect_info.h"
21 namespace content {
23 namespace {
25 // Returns the net load flags to use based on the navigation type.
26 // TODO(clamy): unify the code with what is happening on the renderer side.
27 int LoadFlagFromNavigationType(FrameMsg_Navigate_Type::Value navigation_type) {
28 int load_flags = net::LOAD_NORMAL;
29 switch (navigation_type) {
30 case FrameMsg_Navigate_Type::RELOAD:
31 case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
32 load_flags |= net::LOAD_VALIDATE_CACHE;
33 break;
34 case FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE:
35 load_flags |= net::LOAD_BYPASS_CACHE;
36 break;
37 case FrameMsg_Navigate_Type::RESTORE:
38 load_flags |= net::LOAD_PREFERRING_CACHE;
39 break;
40 case FrameMsg_Navigate_Type::RESTORE_WITH_POST:
41 load_flags |= net::LOAD_ONLY_FROM_CACHE;
42 break;
43 case FrameMsg_Navigate_Type::NORMAL:
44 default:
45 break;
47 return load_flags;
50 } // namespace
52 // static
53 bool NavigationRequest::ShouldMakeNetworkRequest(const GURL& url) {
54 // Data urls should not make network requests.
55 // TODO(clamy): same document navigations should not make network requests.
56 return !url.SchemeIs(url::kDataScheme);
59 // static
60 scoped_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
61 FrameTreeNode* frame_tree_node,
62 const NavigationEntryImpl& entry,
63 FrameMsg_Navigate_Type::Value navigation_type,
64 base::TimeTicks navigation_start) {
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 FrameMsg_UILoadMetricsReportType::Value report_type =
87 FrameMsg_UILoadMetricsReportType::NO_REPORT;
88 base::TimeTicks ui_timestamp = base::TimeTicks();
89 #if defined(OS_ANDROID)
90 if (!entry.intent_received_timestamp().is_null())
91 report_type = FrameMsg_UILoadMetricsReportType::REPORT_INTENT;
92 ui_timestamp = entry.intent_received_timestamp();
93 #endif
95 scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest(
96 frame_tree_node,
97 CommonNavigationParams(entry.GetURL(), entry.GetReferrer(),
98 entry.GetTransitionType(), navigation_type,
99 !entry.IsViewSourceMode(),ui_timestamp,
100 report_type, entry.GetBaseURLForDataURL(),
101 entry.GetHistoryURLForDataURL()),
102 BeginNavigationParams(method, headers.ToString(),
103 LoadFlagFromNavigationType(navigation_type),
104 false),
105 CommitNavigationParams(entry.GetPageState(),
106 entry.GetIsOverridingUserAgent(),
107 navigation_start),
108 request_body, true, &entry));
109 return navigation_request.Pass();
112 // static
113 scoped_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
114 FrameTreeNode* frame_tree_node,
115 const CommonNavigationParams& common_params,
116 const BeginNavigationParams& begin_params,
117 scoped_refptr<ResourceRequestBody> body) {
118 // TODO(clamy): Check if some PageState should be provided here.
119 // TODO(clamy): See how we should handle override of the user agent when the
120 // navigation may start in a renderer and commit in another one.
121 // TODO(clamy): See if the navigation start time should be measured in the
122 // renderer and sent to the browser instead of being measured here.
123 scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest(
124 frame_tree_node, common_params, begin_params,
125 CommitNavigationParams(PageState(), false, base::TimeTicks::Now()),
126 body, false, nullptr));
127 return navigation_request.Pass();
130 NavigationRequest::NavigationRequest(
131 FrameTreeNode* frame_tree_node,
132 const CommonNavigationParams& common_params,
133 const BeginNavigationParams& begin_params,
134 const CommitNavigationParams& commit_params,
135 scoped_refptr<ResourceRequestBody> body,
136 bool browser_initiated,
137 const NavigationEntryImpl* entry)
138 : frame_tree_node_(frame_tree_node),
139 common_params_(common_params),
140 begin_params_(begin_params),
141 commit_params_(commit_params),
142 browser_initiated_(browser_initiated),
143 state_(NOT_STARTED),
144 restore_type_(NavigationEntryImpl::RESTORE_NONE),
145 is_view_source_(false),
146 bindings_(NavigationEntryImpl::kInvalidBindings) {
147 if (entry) {
148 source_site_instance_ = entry->source_site_instance();
149 dest_site_instance_ = entry->site_instance();
150 restore_type_ = entry->restore_type();
151 is_view_source_ = entry->IsViewSourceMode();
152 bindings_ = entry->bindings();
155 const GURL& first_party_for_cookies =
156 frame_tree_node->IsMainFrame()
157 ? common_params.url
158 : frame_tree_node->frame_tree()->root()->current_url();
159 bool parent_is_main_frame = !frame_tree_node->parent() ?
160 false : frame_tree_node->parent()->IsMainFrame();
161 info_.reset(new NavigationRequestInfo(
162 common_params, begin_params, first_party_for_cookies,
163 frame_tree_node->IsMainFrame(), parent_is_main_frame, body));
166 NavigationRequest::~NavigationRequest() {
169 bool NavigationRequest::BeginNavigation() {
170 DCHECK(!loader_);
171 DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE);
172 state_ = STARTED;
174 if (ShouldMakeNetworkRequest(common_params_.url)) {
175 loader_ = NavigationURLLoader::Create(
176 frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
177 frame_tree_node_->frame_tree_node_id(), info_.Pass(), this);
178 return true;
181 // There is no need to make a network request for this navigation, so commit
182 // it immediately.
183 state_ = RESPONSE_STARTED;
184 frame_tree_node_->navigator()->CommitNavigation(
185 frame_tree_node_, nullptr, scoped_ptr<StreamHandle>());
186 return false;
188 // TODO(davidben): Fire (and add as necessary) observer methods such as
189 // DidStartProvisionalLoadForFrame for the navigation.
192 void NavigationRequest::OnRequestRedirected(
193 const net::RedirectInfo& redirect_info,
194 const scoped_refptr<ResourceResponse>& response) {
195 // TODO(davidben): Track other changes from redirects. These are important
196 // for, e.g., reloads.
197 common_params_.url = redirect_info.new_url;
199 // TODO(davidben): This where prerender and navigation_interceptor should be
200 // integrated. For now, just always follow all redirects.
201 loader_->FollowRedirect();
204 void NavigationRequest::OnResponseStarted(
205 const scoped_refptr<ResourceResponse>& response,
206 scoped_ptr<StreamHandle> body) {
207 DCHECK(state_ == STARTED);
208 state_ = RESPONSE_STARTED;
209 frame_tree_node_->navigator()->CommitNavigation(frame_tree_node_,
210 response.get(), body.Pass());
213 void NavigationRequest::OnRequestFailed(int net_error) {
214 DCHECK(state_ == STARTED);
215 state_ = FAILED;
216 // TODO(davidben): Network failures should display a network error page.
217 NOTIMPLEMENTED() << " where net_error=" << net_error;
220 void NavigationRequest::OnRequestStarted(base::TimeTicks timestamp) {
221 frame_tree_node_->navigator()->LogResourceRequestTime(timestamp,
222 common_params_.url);
225 } // namespace content