OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading | 5 // See http://dev.chromium.org/developers/design-documents/multi-process-resourc
e-loading |
6 | 6 |
7 #include "content/child/resource_dispatcher.h" | 7 #include "content/child/resource_dispatcher.h" |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "content/child/sync_load_response.h" | 21 #include "content/child/sync_load_response.h" |
22 #include "content/common/inter_process_time_ticks_converter.h" | 22 #include "content/common/inter_process_time_ticks_converter.h" |
23 #include "content/common/resource_messages.h" | 23 #include "content/common/resource_messages.h" |
24 #include "content/public/child/request_peer.h" | 24 #include "content/public/child/request_peer.h" |
25 #include "content/public/child/resource_dispatcher_delegate.h" | 25 #include "content/public/child/resource_dispatcher_delegate.h" |
26 #include "content/public/common/resource_response.h" | 26 #include "content/public/common/resource_response.h" |
27 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
28 #include "net/base/net_util.h" | 28 #include "net/base/net_util.h" |
29 #include "net/base/request_priority.h" | 29 #include "net/base/request_priority.h" |
30 #include "net/http/http_response_headers.h" | 30 #include "net/http/http_response_headers.h" |
31 #include "webkit/child/resource_loader_bridge.h" | |
32 #include "webkit/common/resource_type.h" | 31 #include "webkit/common/resource_type.h" |
33 | 32 |
34 using webkit_glue::ResourceLoaderBridge; | |
35 using webkit_glue::ResourceResponseInfo; | 33 using webkit_glue::ResourceResponseInfo; |
36 | 34 |
37 namespace content { | 35 namespace content { |
38 | 36 |
39 namespace { | 37 namespace { |
40 | 38 |
41 // Converts |time| from a remote to local TimeTicks, overwriting the original | 39 // Converts |time| from a remote to local TimeTicks, overwriting the original |
42 // value. | 40 // value. |
43 void RemoteToLocalTimeTicks( | 41 void RemoteToLocalTimeTicks( |
44 const InterProcessTimeTicksConverter& converter, | 42 const InterProcessTimeTicksConverter& converter, |
45 base::TimeTicks* time) { | 43 base::TimeTicks* time) { |
46 RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time); | 44 RemoteTimeTicks remote_time = RemoteTimeTicks::FromTimeTicks(*time); |
47 *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks(); | 45 *time = converter.ToLocalTimeTicks(remote_time).ToTimeTicks(); |
48 } | 46 } |
49 | 47 |
50 | 48 void CrashOnMapFailure() { |
51 } // namespace | |
52 | |
53 static void CrashOnMapFailure() { | |
54 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
55 DWORD last_err = GetLastError(); | 50 DWORD last_err = GetLastError(); |
56 base::debug::Alias(&last_err); | 51 base::debug::Alias(&last_err); |
57 #endif | 52 #endif |
58 CHECK(false); | 53 CHECK(false); |
59 } | 54 } |
60 | 55 |
61 // Each resource request is assigned an ID scoped to this process. | 56 // Each resource request is assigned an ID scoped to this process. |
62 static int MakeRequestID() { | 57 int MakeRequestID() { |
63 // NOTE: The resource_dispatcher_host also needs probably unique | 58 // NOTE: The resource_dispatcher_host also needs probably unique |
64 // request_ids, so they count down from -2 (-1 is a special we're | 59 // request_ids, so they count down from -2 (-1 is a special we're |
65 // screwed value), while the renderer process counts up. | 60 // screwed value), while the renderer process counts up. |
66 static int next_request_id = 0; | 61 static int next_request_id = 0; |
67 return next_request_id++; | 62 return next_request_id++; |
68 } | 63 } |
69 | 64 |
70 // ResourceLoaderBridge implementation ---------------------------------------- | 65 } // namespace |
71 | 66 |
72 class IPCResourceLoaderBridge : public ResourceLoaderBridge { | 67 class ResourceDispatcher::IPCResourceLoaderBridge { |
73 public: | 68 public: |
74 IPCResourceLoaderBridge(ResourceDispatcher* dispatcher, | 69 IPCResourceLoaderBridge(ResourceDispatcher* dispatcher, |
75 const RequestInfo& request_info); | 70 const RequestInfo& request_info); |
76 virtual ~IPCResourceLoaderBridge(); | 71 virtual ~IPCResourceLoaderBridge(); |
77 | 72 |
78 // ResourceLoaderBridge | 73 void SetRequestBody(ResourceRequestBody* request_body); |
79 virtual void SetRequestBody(ResourceRequestBody* request_body) OVERRIDE; | 74 bool Start(RequestPeer* peer); |
80 virtual bool Start(RequestPeer* peer) OVERRIDE; | 75 void Cancel(); |
81 virtual void Cancel() OVERRIDE; | 76 void SetDefersLoading(bool value); |
82 virtual void SetDefersLoading(bool value) OVERRIDE; | 77 void DidChangePriority(net::RequestPriority new_priority); |
83 virtual void DidChangePriority(net::RequestPriority new_priority) OVERRIDE; | 78 void SyncLoad(SyncLoadResponse* response); |
84 virtual void SyncLoad(SyncLoadResponse* response) OVERRIDE; | |
85 | 79 |
86 private: | 80 private: |
87 RequestPeer* peer_; | 81 RequestPeer* peer_; |
88 | 82 |
89 // The resource dispatcher for this loader. The bridge doesn't own it, but | 83 // The resource dispatcher for this loader. The bridge doesn't own it, but |
90 // it's guaranteed to outlive the bridge. | 84 // it's guaranteed to outlive the bridge. |
91 ResourceDispatcher* dispatcher_; | 85 ResourceDispatcher* dispatcher_; |
92 | 86 |
93 // The request to send, created on initialization for modification and | 87 // The request to send, created on initialization for modification and |
94 // appending data. | 88 // appending data. |
95 ResourceHostMsg_Request request_; | 89 ResourceHostMsg_Request request_; |
96 | 90 |
97 // ID for the request, valid once Start()ed, -1 if not valid yet. | 91 // ID for the request, valid once Start()ed, -1 if not valid yet. |
98 int request_id_; | 92 int request_id_; |
99 | 93 |
100 // The routing id used when sending IPC messages. | 94 // The routing id used when sending IPC messages. |
101 int routing_id_; | 95 int routing_id_; |
102 | 96 |
103 // The security origin of the frame that initiates this request. | 97 // The security origin of the frame that initiates this request. |
104 GURL frame_origin_; | 98 GURL frame_origin_; |
105 | 99 |
106 bool is_synchronous_request_; | 100 bool is_synchronous_request_; |
107 }; | 101 }; |
108 | 102 |
109 IPCResourceLoaderBridge::IPCResourceLoaderBridge( | 103 ResourceDispatcher::IPCResourceLoaderBridge::IPCResourceLoaderBridge( |
110 ResourceDispatcher* dispatcher, | 104 ResourceDispatcher* dispatcher, |
111 const RequestInfo& request_info) | 105 const RequestInfo& request_info) |
112 : peer_(NULL), | 106 : peer_(NULL), |
113 dispatcher_(dispatcher), | 107 dispatcher_(dispatcher), |
114 request_id_(-1), | 108 request_id_(-1), |
115 routing_id_(request_info.routing_id), | 109 routing_id_(request_info.routing_id), |
116 is_synchronous_request_(false) { | 110 is_synchronous_request_(false) { |
117 DCHECK(dispatcher_) << "no resource dispatcher"; | 111 DCHECK(dispatcher_) << "no resource dispatcher"; |
118 request_.method = request_info.method; | 112 request_.method = request_info.method; |
119 request_.url = request_info.url; | 113 request_.url = request_info.url; |
(...skipping 27 matching lines...) Expand all Loading... |
147 extra_data->should_replace_current_entry(); | 141 extra_data->should_replace_current_entry(); |
148 request_.transferred_request_child_id = | 142 request_.transferred_request_child_id = |
149 extra_data->transferred_request_child_id(); | 143 extra_data->transferred_request_child_id(); |
150 request_.transferred_request_request_id = | 144 request_.transferred_request_request_id = |
151 extra_data->transferred_request_request_id(); | 145 extra_data->transferred_request_request_id(); |
152 request_.service_worker_provider_id = | 146 request_.service_worker_provider_id = |
153 extra_data->service_worker_provider_id(); | 147 extra_data->service_worker_provider_id(); |
154 frame_origin_ = extra_data->frame_origin(); | 148 frame_origin_ = extra_data->frame_origin(); |
155 } | 149 } |
156 | 150 |
157 IPCResourceLoaderBridge::~IPCResourceLoaderBridge() { | 151 ResourceDispatcher::IPCResourceLoaderBridge::~IPCResourceLoaderBridge() { |
158 // we remove our hook for the resource dispatcher only when going away, since | 152 // we remove our hook for the resource dispatcher only when going away, since |
159 // it doesn't keep track of whether we've force terminated the request | 153 // it doesn't keep track of whether we've force terminated the request |
160 if (request_id_ >= 0) { | 154 if (request_id_ >= 0) { |
161 // this operation may fail, as the dispatcher will have preemptively | 155 // this operation may fail, as the dispatcher will have preemptively |
162 // removed us when the renderer sends the ReceivedAllData message. | 156 // removed us when the renderer sends the ReceivedAllData message. |
163 dispatcher_->RemovePendingRequest(request_id_); | 157 dispatcher_->RemovePendingRequest(request_id_); |
164 | 158 |
165 if (request_.download_to_file) { | 159 if (request_.download_to_file) { |
166 dispatcher_->message_sender()->Send( | 160 dispatcher_->message_sender()->Send( |
167 new ResourceHostMsg_ReleaseDownloadedFile(request_id_)); | 161 new ResourceHostMsg_ReleaseDownloadedFile(request_id_)); |
168 } | 162 } |
169 } | 163 } |
170 } | 164 } |
171 | 165 |
172 void IPCResourceLoaderBridge::SetRequestBody( | 166 void ResourceDispatcher::IPCResourceLoaderBridge::SetRequestBody( |
173 ResourceRequestBody* request_body) { | 167 ResourceRequestBody* request_body) { |
174 DCHECK(request_id_ == -1) << "request already started"; | 168 DCHECK(request_id_ == -1) << "request already started"; |
175 request_.request_body = request_body; | 169 request_.request_body = request_body; |
176 } | 170 } |
177 | 171 |
178 // Writes a footer on the message and sends it | 172 // Writes a footer on the message and sends it |
179 bool IPCResourceLoaderBridge::Start(RequestPeer* peer) { | 173 bool ResourceDispatcher::IPCResourceLoaderBridge::Start(RequestPeer* peer) { |
180 if (request_id_ != -1) { | 174 if (request_id_ != -1) { |
181 NOTREACHED() << "Starting a request twice"; | 175 NOTREACHED() << "Starting a request twice"; |
182 return false; | 176 return false; |
183 } | 177 } |
184 | 178 |
185 peer_ = peer; | 179 peer_ = peer; |
186 | 180 |
187 // generate the request ID, and append it to the message | 181 // generate the request ID, and append it to the message |
188 request_id_ = dispatcher_->AddPendingRequest(peer_, | 182 request_id_ = dispatcher_->AddPendingRequest(peer_, |
189 request_.resource_type, | 183 request_.resource_type, |
190 request_.origin_pid, | 184 request_.origin_pid, |
191 frame_origin_, | 185 frame_origin_, |
192 request_.url); | 186 request_.url); |
193 | 187 |
194 return dispatcher_->message_sender()->Send( | 188 return dispatcher_->message_sender()->Send( |
195 new ResourceHostMsg_RequestResource(routing_id_, request_id_, request_)); | 189 new ResourceHostMsg_RequestResource(routing_id_, request_id_, request_)); |
196 } | 190 } |
197 | 191 |
198 void IPCResourceLoaderBridge::Cancel() { | 192 void ResourceDispatcher::IPCResourceLoaderBridge::Cancel() { |
199 if (request_id_ < 0) { | 193 if (request_id_ < 0) { |
200 NOTREACHED() << "Trying to cancel an unstarted request"; | 194 NOTREACHED() << "Trying to cancel an unstarted request"; |
201 return; | 195 return; |
202 } | 196 } |
203 | 197 |
204 if (!is_synchronous_request_) | 198 if (!is_synchronous_request_) |
205 dispatcher_->CancelPendingRequest(request_id_); | 199 dispatcher_->CancelPendingRequest(request_id_); |
206 | 200 |
207 // We can't remove the request ID from the resource dispatcher because more | 201 // We can't remove the request ID from the resource dispatcher because more |
208 // data might be pending. Sending the cancel message may cause more data | 202 // data might be pending. Sending the cancel message may cause more data |
209 // to be flushed, and will then cause a complete message to be sent. | 203 // to be flushed, and will then cause a complete message to be sent. |
210 } | 204 } |
211 | 205 |
212 void IPCResourceLoaderBridge::SetDefersLoading(bool value) { | 206 void ResourceDispatcher::IPCResourceLoaderBridge::SetDefersLoading(bool value) { |
213 if (request_id_ < 0) { | 207 if (request_id_ < 0) { |
214 NOTREACHED() << "Trying to (un)defer an unstarted request"; | 208 NOTREACHED() << "Trying to (un)defer an unstarted request"; |
215 return; | 209 return; |
216 } | 210 } |
217 | 211 |
218 dispatcher_->SetDefersLoading(request_id_, value); | 212 dispatcher_->SetDefersLoading(request_id_, value); |
219 } | 213 } |
220 | 214 |
221 void IPCResourceLoaderBridge::DidChangePriority( | 215 void ResourceDispatcher::IPCResourceLoaderBridge::DidChangePriority( |
222 net::RequestPriority new_priority) { | 216 net::RequestPriority new_priority) { |
223 if (request_id_ < 0) { | 217 if (request_id_ < 0) { |
224 NOTREACHED() << "Trying to change priority of an unstarted request"; | 218 NOTREACHED() << "Trying to change priority of an unstarted request"; |
225 return; | 219 return; |
226 } | 220 } |
227 | 221 |
228 dispatcher_->DidChangePriority(routing_id_, request_id_, new_priority); | 222 dispatcher_->DidChangePriority(routing_id_, request_id_, new_priority); |
229 } | 223 } |
230 | 224 |
231 void IPCResourceLoaderBridge::SyncLoad(SyncLoadResponse* response) { | 225 void ResourceDispatcher::IPCResourceLoaderBridge::SyncLoad( |
| 226 SyncLoadResponse* response) { |
232 if (request_id_ != -1) { | 227 if (request_id_ != -1) { |
233 NOTREACHED() << "Starting a request twice"; | 228 NOTREACHED() << "Starting a request twice"; |
234 response->error_code = net::ERR_FAILED; | 229 response->error_code = net::ERR_FAILED; |
235 return; | 230 return; |
236 } | 231 } |
237 | 232 |
238 request_id_ = MakeRequestID(); | 233 request_id_ = MakeRequestID(); |
239 is_synchronous_request_ = true; | 234 is_synchronous_request_ = true; |
240 | 235 |
241 SyncLoadResult result; | 236 SyncLoadResult result; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 if (request_info->is_deferred) { | 304 if (request_info->is_deferred) { |
310 request_info->deferred_message_queue.push_back(new IPC::Message(message)); | 305 request_info->deferred_message_queue.push_back(new IPC::Message(message)); |
311 return true; | 306 return true; |
312 } | 307 } |
313 } | 308 } |
314 | 309 |
315 DispatchMessage(message); | 310 DispatchMessage(message); |
316 return true; | 311 return true; |
317 } | 312 } |
318 | 313 |
| 314 void ResourceDispatcher::CreateBridge(const RequestInfo& info) { |
| 315 bridge_.reset(new IPCResourceLoaderBridge(this, info)); |
| 316 } |
| 317 |
| 318 void ResourceDispatcher::SetRequestBody(ResourceRequestBody* request_body) { |
| 319 if (bridge_) |
| 320 bridge_->SetRequestBody(request_body); |
| 321 } |
| 322 |
| 323 bool ResourceDispatcher::Start(RequestPeer* peer) { |
| 324 if (bridge_) |
| 325 return bridge_->Start(peer); |
| 326 return false; |
| 327 } |
| 328 |
| 329 void ResourceDispatcher::Cancel() { |
| 330 if (bridge_) |
| 331 bridge_->Cancel(); |
| 332 } |
| 333 |
| 334 void ResourceDispatcher::SetDefersLoading(bool value) { |
| 335 if (bridge_) |
| 336 bridge_->SetDefersLoading(value); |
| 337 } |
| 338 |
| 339 void ResourceDispatcher::DidChangePriority(net::RequestPriority new_priority) { |
| 340 if (bridge_) |
| 341 bridge_->DidChangePriority(new_priority); |
| 342 } |
| 343 |
| 344 void ResourceDispatcher::SyncLoad(SyncLoadResponse* response) { |
| 345 if (bridge_) |
| 346 bridge_->SyncLoad(response); |
| 347 } |
| 348 |
319 ResourceDispatcher::PendingRequestInfo* | 349 ResourceDispatcher::PendingRequestInfo* |
320 ResourceDispatcher::GetPendingRequestInfo(int request_id) { | 350 ResourceDispatcher::GetPendingRequestInfo(int request_id) { |
321 PendingRequestList::iterator it = pending_requests_.find(request_id); | 351 PendingRequestList::iterator it = pending_requests_.find(request_id); |
322 if (it == pending_requests_.end()) { | 352 if (it == pending_requests_.end()) { |
323 // This might happen for kill()ed requests on the webkit end. | 353 // This might happen for kill()ed requests on the webkit end. |
324 return NULL; | 354 return NULL; |
325 } | 355 } |
326 return &(it->second); | 356 return &(it->second); |
327 } | 357 } |
328 | 358 |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 if (index != pending_requests_.end()) { | 714 if (index != pending_requests_.end()) { |
685 PendingRequestInfo& pending_request = index->second; | 715 PendingRequestInfo& pending_request = index->second; |
686 if (pending_request.is_deferred) { | 716 if (pending_request.is_deferred) { |
687 pending_request.deferred_message_queue.swap(q); | 717 pending_request.deferred_message_queue.swap(q); |
688 return; | 718 return; |
689 } | 719 } |
690 } | 720 } |
691 } | 721 } |
692 } | 722 } |
693 | 723 |
694 ResourceLoaderBridge* ResourceDispatcher::CreateBridge( | |
695 const RequestInfo& request_info) { | |
696 return new IPCResourceLoaderBridge(this, request_info); | |
697 } | |
698 | |
699 void ResourceDispatcher::ToResourceResponseInfo( | 724 void ResourceDispatcher::ToResourceResponseInfo( |
700 const PendingRequestInfo& request_info, | 725 const PendingRequestInfo& request_info, |
701 const ResourceResponseHead& browser_info, | 726 const ResourceResponseHead& browser_info, |
702 ResourceResponseInfo* renderer_info) const { | 727 ResourceResponseInfo* renderer_info) const { |
703 *renderer_info = browser_info; | 728 *renderer_info = browser_info; |
704 if (request_info.request_start.is_null() || | 729 if (request_info.request_start.is_null() || |
705 request_info.response_start.is_null() || | 730 request_info.response_start.is_null() || |
706 browser_info.request_start.is_null() || | 731 browser_info.request_start.is_null() || |
707 browser_info.response_start.is_null() || | 732 browser_info.response_start.is_null() || |
708 browser_info.load_timing.request_start.is_null()) { | 733 browser_info.load_timing.request_start.is_null()) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) { | 827 void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) { |
803 while (!queue->empty()) { | 828 while (!queue->empty()) { |
804 IPC::Message* message = queue->front(); | 829 IPC::Message* message = queue->front(); |
805 ReleaseResourcesInDataMessage(*message); | 830 ReleaseResourcesInDataMessage(*message); |
806 queue->pop_front(); | 831 queue->pop_front(); |
807 delete message; | 832 delete message; |
808 } | 833 } |
809 } | 834 } |
810 | 835 |
811 } // namespace content | 836 } // namespace content |
OLD | NEW |