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