| 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 |