1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This is the browser side of the resource dispatcher, it receives requests
// from the child process (i.e. [Renderer, Plugin, Worker]ProcessHost), and
// dispatches them to URLRequests. It then forwards the messages from the
// URLRequests back to the correct process for handling.
//
// See http://dev.chromium.org/developers/design-documents/multi-process-resource-loading
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_DISPATCHER_HOST_IMPL_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_DISPATCHER_HOST_IMPL_H_
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_loader.h"
#include "content/browser/loader/resource_loader_delegate.h"
#include "content/browser/loader/resource_scheduler.h"
#include "content/common/content_export.h"
#include "content/common/resource_request_body.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/common/resource_type.h"
#include "ipc/ipc_message.h"
#include "net/cookies/canonical_cookie.h"
#include "net/url_request/url_request.h"
class ResourceHandler;
struct ResourceHostMsg_Request;
namespace net {
class URLRequestJobFactory;
}
namespace storage {
class ShareableFileReference;
}
namespace content {
class AppCacheService;
class NavigationURLLoaderImplCore;
class ResourceContext;
class ResourceDispatcherHostDelegate;
class ResourceMessageDelegate;
class ResourceMessageFilter;
class ResourceRequestInfoImpl;
class SaveFileManager;
class WebContentsImpl;
struct CommonNavigationParams;
struct DownloadSaveInfo;
struct NavigationRequestInfo;
struct Referrer;
class CONTENT_EXPORT ResourceDispatcherHostImpl
: public ResourceDispatcherHost,
public ResourceLoaderDelegate {
public:
ResourceDispatcherHostImpl();
~ResourceDispatcherHostImpl() override;
// Returns the current ResourceDispatcherHostImpl. May return NULL if it
// hasn't been created yet.
static ResourceDispatcherHostImpl* Get();
// ResourceDispatcherHost implementation:
void SetDelegate(ResourceDispatcherHostDelegate* delegate) override;
void SetAllowCrossOriginAuthPrompt(bool value) override;
DownloadInterruptReason BeginDownload(
scoped_ptr<net::URLRequest> request,
const Referrer& referrer,
bool is_content_initiated,
ResourceContext* context,
int child_id,
int route_id,
bool prefer_cache,
scoped_ptr<DownloadSaveInfo> save_info,
uint32 download_id,
const DownloadStartedCallback& started_callback) override;
void ClearLoginDelegateForRequest(net::URLRequest* request) override;
void BlockRequestsForRoute(int child_id, int route_id) override;
void ResumeBlockedRequestsForRoute(int child_id, int route_id) override;
// Puts the resource dispatcher host in an inactive state (unable to begin
// new requests). Cancels all pending requests.
void Shutdown();
// Notify the ResourceDispatcherHostImpl of a new resource context.
void AddResourceContext(ResourceContext* context);
// Notify the ResourceDispatcherHostImpl of a resource context destruction.
void RemoveResourceContext(ResourceContext* context);
// Resumes a request that deferred at response start.
void ResumeResponseDeferredAtStart(const GlobalRequestID& id);
// Force cancels any pending requests for the given |context|. This is
// necessary to ensure that before |context| goes away, all requests
// for it are dead.
void CancelRequestsForContext(ResourceContext* context);
// Returns true if the message was a resource message that was processed.
bool OnMessageReceived(const IPC::Message& message,
ResourceMessageFilter* filter);
// Initiates a save file from the browser process (as opposed to a resource
// request from the renderer or another child process).
void BeginSaveFile(const GURL& url,
const Referrer& referrer,
int child_id,
int route_id,
ResourceContext* context);
// Cancels the given request if it still exists.
void CancelRequest(int child_id, int request_id);
// Marks the request as "parked". This happens if a request is
// redirected cross-site and needs to be resumed by a new render view.
void MarkAsTransferredNavigation(const GlobalRequestID& id);
// Cancels a request previously marked as being transferred, for use when a
// navigation was cancelled.
void CancelTransferringNavigation(const GlobalRequestID& id);
// Resumes the request without transferring it to a new render view.
void ResumeDeferredNavigation(const GlobalRequestID& id);
// Returns the number of pending requests. This is designed for the unittests
int pending_requests() const {
return static_cast<int>(pending_loaders_.size());
}
// Intended for unit-tests only. Overrides the outstanding requests bound.
void set_max_outstanding_requests_cost_per_process(int limit) {
max_outstanding_requests_cost_per_process_ = limit;
}
void set_max_num_in_flight_requests_per_process(int limit) {
max_num_in_flight_requests_per_process_ = limit;
}
void set_max_num_in_flight_requests(int limit) {
max_num_in_flight_requests_ = limit;
}
// The average private bytes increase of the browser for each new pending
// request. Experimentally obtained.
static const int kAvgBytesPerOutstandingRequest = 4400;
SaveFileManager* save_file_manager() const {
return save_file_manager_.get();
}
// Called when a RenderViewHost is created.
void OnRenderViewHostCreated(int child_id,
int route_id,
bool is_visible,
bool is_audible);
// Called when a RenderViewHost is deleted.
void OnRenderViewHostDeleted(int child_id, int route_id);
// Called when a RenderViewHost starts or stops loading.
void OnRenderViewHostSetIsLoading(int child_id,
int route_id,
bool is_loading);
// Called when a RenderViewHost is hidden.
void OnRenderViewHostWasHidden(int child_id, int route_id);
// Called when a RenderViewHost is shown.
void OnRenderViewHostWasShown(int child_id, int route_id);
// Called when an AudioRenderHost starts or stops playing.
void OnAudioRenderHostStreamStateChanged(int child_id,
int route_id,
bool is_playing);
// Force cancels any pending requests for the given process.
void CancelRequestsForProcess(int child_id);
void OnUserGesture(WebContentsImpl* contents);
// Retrieves a net::URLRequest. Must be called from the IO thread.
net::URLRequest* GetURLRequest(const GlobalRequestID& request_id);
void RemovePendingRequest(int child_id, int request_id);
// Cancels any blocked request for the specified route id.
void CancelBlockedRequestsForRoute(int child_id, int route_id);
// Maintains a collection of temp files created in support of
// the download_to_file capability. Used to grant access to the
// child process and to defer deletion of the file until it's
// no longer needed.
void RegisterDownloadedTempFile(
int child_id, int request_id,
const base::FilePath& file_path);
void UnregisterDownloadedTempFile(int child_id, int request_id);
// Needed for the sync IPC message dispatcher macros.
bool Send(IPC::Message* message);
// Indicates whether third-party sub-content can pop-up HTTP basic auth
// dialog boxes.
bool allow_cross_origin_auth_prompt();
ResourceDispatcherHostDelegate* delegate() {
return delegate_;
}
// Must be called after the ResourceRequestInfo has been created
// and associated with the request.
// |id| should be |content::DownloadItem::kInvalidId| to request automatic
// assignment. This is marked virtual so it can be overriden in testing.
virtual scoped_ptr<ResourceHandler> CreateResourceHandlerForDownload(
net::URLRequest* request,
bool is_content_initiated,
bool must_download,
uint32 id,
scoped_ptr<DownloadSaveInfo> save_info,
const DownloadUrlParameters::OnStartedCallback& started_cb);
// Must be called after the ResourceRequestInfo has been created
// and associated with the request. If |payload| is set to a non-empty value,
// the value will be sent to the old resource handler instead of canceling
// it, except on HTTP errors. This is marked virtual so it can be overriden in
// testing.
virtual scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
net::URLRequest* request,
ResourceResponse* response,
std::string* payload);
ResourceScheduler* scheduler() { return scheduler_.get(); }
// Called by a ResourceHandler when it's ready to start reading data and
// sending it to the renderer. Returns true if there are enough file
// descriptors available for the shared memory buffer. If false is returned,
// the request should cancel.
bool HasSufficientResourcesForRequest(net::URLRequest* request);
// Called by a ResourceHandler after it has finished its request and is done
// using its shared memory buffer. Frees up that file descriptor to be used
// elsewhere.
void FinishedWithResourcesForRequest(net::URLRequest* request);
// PlzNavigate: Begins a request for NavigationURLLoader. |loader| is the
// loader to attach to the leaf resource handler.
void BeginNavigationRequest(ResourceContext* resource_context,
int64 frame_tree_node_id,
const CommonNavigationParams& common_params,
const NavigationRequestInfo& info,
scoped_refptr<ResourceRequestBody> request_body,
NavigationURLLoaderImplCore* loader);
private:
friend class ResourceDispatcherHostTest;
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
TestBlockedRequestsProcessDies);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
CalculateApproximateMemoryCost);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
DetachableResourceTimesOut);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
TestProcessCancelDetachableTimesOut);
class ShutdownTask;
struct OustandingRequestsStats {
int memory_cost;
int num_requests;
};
friend class ShutdownTask;
friend class ResourceMessageDelegate;
// ResourceLoaderDelegate implementation:
ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
ResourceLoader* loader,
net::AuthChallengeInfo* auth_info) override;
bool HandleExternalProtocol(ResourceLoader* loader, const GURL& url) override;
void DidStartRequest(ResourceLoader* loader) override;
void DidReceiveRedirect(ResourceLoader* loader, const GURL& new_url) override;
void DidReceiveResponse(ResourceLoader* loader) override;
void DidFinishLoading(ResourceLoader* loader) override;
// An init helper that runs on the IO thread.
void OnInit();
// A shutdown helper that runs on the IO thread.
void OnShutdown();
// Helper function for regular and download requests.
void BeginRequestInternal(scoped_ptr<net::URLRequest> request,
scoped_ptr<ResourceHandler> handler);
void StartLoading(ResourceRequestInfoImpl* info,
const linked_ptr<ResourceLoader>& loader);
// We keep track of how much memory each request needs and how many requests
// are issued by each renderer. These are known as OustandingRequestStats.
// Memory limits apply to all requests sent to us by the renderers. There is a
// limit for each renderer. File descriptor limits apply to requests that are
// receiving their body. These are known as in-flight requests. There is a
// global limit that applies for the browser process. Each render is allowed
// to use up to a fraction of that.
// Returns the OustandingRequestsStats for |info|'s renderer, or an empty
// struct if that renderer has no outstanding requests.
OustandingRequestsStats GetOutstandingRequestsStats(
const ResourceRequestInfoImpl& info);
// Updates |outstanding_requests_stats_map_| with the specified |stats| for
// the renderer that made the request in |info|.
void UpdateOutstandingRequestsStats(const ResourceRequestInfoImpl& info,
const OustandingRequestsStats& stats);
// Called every time an outstanding request is created or deleted. |count|
// indicates whether the request is new or deleted. |count| must be 1 or -1.
OustandingRequestsStats IncrementOutstandingRequestsMemory(
int count,
const ResourceRequestInfoImpl& info);
// Called when an in flight request allocates or releases a shared memory
// buffer. |count| indicates whether the request is issuing or finishing.
// |count| must be 1 or -1.
OustandingRequestsStats IncrementOutstandingRequestsCount(
int count,
ResourceRequestInfoImpl* info);
// Estimate how much heap space |request| will consume to run.
static int CalculateApproximateMemoryCost(net::URLRequest* request);
// Force cancels any pending requests for the given route id. This method
// acts like CancelRequestsForProcess when route_id is -1.
void CancelRequestsForRoute(int child_id, int route_id);
// The list of all requests that we have pending. This list is not really
// optimized, and assumes that we have relatively few requests pending at once
// since some operations require brute-force searching of the list.
//
// It may be enhanced in the future to provide some kind of prioritization
// mechanism. We should also consider a hashtable or binary tree if it turns
// out we have a lot of things here.
typedef std::map<GlobalRequestID, linked_ptr<ResourceLoader> > LoaderMap;
// Deletes the pending request identified by the iterator passed in.
// This function will invalidate the iterator passed in. Callers should
// not rely on this iterator being valid on return.
void RemovePendingLoader(const LoaderMap::iterator& iter);
// Checks all pending requests and updates the load states and upload
// progress if necessary.
void UpdateLoadStates();
// Resumes or cancels (if |cancel_requests| is true) any blocked requests.
void ProcessBlockedRequestsForRoute(int child_id,
int route_id,
bool cancel_requests);
void OnRequestResource(int routing_id,
int request_id,
const ResourceHostMsg_Request& request_data);
void OnSyncLoad(int request_id,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result);
// Update the ResourceRequestInfo and internal maps when a request is
// transferred from one process to another.
void UpdateRequestForTransfer(int child_id,
int route_id,
int request_id,
const ResourceHostMsg_Request& request_data,
const linked_ptr<ResourceLoader>& loader);
void BeginRequest(int request_id,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result, // only valid for sync
int route_id); // only valid for async
// Creates a ResourceHandler to be used by BeginRequest() for normal resource
// loading.
scoped_ptr<ResourceHandler> CreateResourceHandler(
net::URLRequest* request,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result,
int route_id,
int process_type,
int child_id,
ResourceContext* resource_context);
// Wraps |handler| in the standard resource handlers for normal resource
// loading and navigation requests. This adds BufferedResourceHandler and
// ResourceThrottles.
scoped_ptr<ResourceHandler> AddStandardHandlers(
net::URLRequest* request,
ResourceType resource_type,
ResourceContext* resource_context,
AppCacheService* appcache_service,
int child_id,
int route_id,
scoped_ptr<ResourceHandler> handler);
void OnDataDownloadedACK(int request_id);
void OnUploadProgressACK(int request_id);
void OnCancelRequest(int request_id);
void OnReleaseDownloadedFile(int request_id);
// Creates ResourceRequestInfoImpl for a download or page save.
// |download| should be true if the request is a file download.
ResourceRequestInfoImpl* CreateRequestInfo(
int child_id,
int route_id,
bool download,
ResourceContext* context);
// Relationship of resource being authenticated with the top level page.
enum HttpAuthRelationType {
HTTP_AUTH_RELATION_TOP, // Top-level page itself
HTTP_AUTH_RELATION_SAME_DOMAIN, // Sub-content from same domain
HTTP_AUTH_RELATION_BLOCKED_CROSS, // Blocked Sub-content from cross domain
HTTP_AUTH_RELATION_ALLOWED_CROSS, // Allowed Sub-content per command line
HTTP_AUTH_RELATION_LAST
};
HttpAuthRelationType HttpAuthRelationTypeOf(const GURL& request_url,
const GURL& first_party);
// Returns whether the URLRequest identified by |transferred_request_id| is
// currently in the process of being transferred to a different renderer.
// This happens if a request is redirected cross-site and needs to be resumed
// by a new render view.
bool IsTransferredNavigation(
const GlobalRequestID& transferred_request_id) const;
ResourceLoader* GetLoader(const GlobalRequestID& id) const;
ResourceLoader* GetLoader(int child_id, int request_id) const;
// Registers |delegate| to receive resource IPC messages targeted to the
// specified |id|.
void RegisterResourceMessageDelegate(const GlobalRequestID& id,
ResourceMessageDelegate* delegate);
void UnregisterResourceMessageDelegate(const GlobalRequestID& id,
ResourceMessageDelegate* delegate);
int BuildLoadFlagsForRequest(const ResourceHostMsg_Request& request_data,
int child_id,
bool is_sync_load);
LoaderMap pending_loaders_;
// Collection of temp files downloaded for child processes via
// the download_to_file mechanism. We avoid deleting them until
// the client no longer needs them.
typedef std::map<int, scoped_refptr<storage::ShareableFileReference> >
DeletableFilesMap; // key is request id
typedef std::map<int, DeletableFilesMap>
RegisteredTempFiles; // key is child process id
RegisteredTempFiles registered_temp_files_;
// A timer that periodically calls UpdateLoadStates while pending_requests_
// is not empty.
scoped_ptr<base::RepeatingTimer<ResourceDispatcherHostImpl> >
update_load_states_timer_;
// We own the save file manager.
scoped_refptr<SaveFileManager> save_file_manager_;
// Request ID for browser initiated requests. request_ids generated by
// child processes are counted up from 0, while browser created requests
// start at -2 and go down from there. (We need to start at -2 because -1 is
// used as a special value all over the resource_dispatcher_host for
// uninitialized variables.) This way, we no longer have the unlikely (but
// observed in the real world!) event where we have two requests with the same
// request_id_.
int request_id_;
// True if the resource dispatcher host has been shut down.
bool is_shutdown_;
typedef std::vector<linked_ptr<ResourceLoader> > BlockedLoadersList;
typedef std::map<GlobalRoutingID, BlockedLoadersList*> BlockedLoadersMap;
BlockedLoadersMap blocked_loaders_map_;
// Maps the child_ids to the approximate number of bytes
// being used to service its resource requests. No entry implies 0 cost.
typedef std::map<int, OustandingRequestsStats> OutstandingRequestsStatsMap;
OutstandingRequestsStatsMap outstanding_requests_stats_map_;
// |num_in_flight_requests_| is the total number of requests currently issued
// summed across all renderers.
int num_in_flight_requests_;
// |max_num_in_flight_requests_| is the upper bound on how many requests
// can be in flight at once. It's based on the maximum number of file
// descriptors open per process. We need a global limit for the browser
// process.
int max_num_in_flight_requests_;
// |max_num_in_flight_requests_| is the upper bound on how many requests
// can be issued at once. It's based on the maximum number of file
// descriptors open per process. We need a per-renderer limit so that no
// single renderer can hog the browser's limit.
int max_num_in_flight_requests_per_process_;
// |max_outstanding_requests_cost_per_process_| is the upper bound on how
// many outstanding requests can be issued per child process host.
// The constraint is expressed in terms of bytes (where the cost of
// individual requests is given by CalculateApproximateMemoryCost).
// The total number of outstanding requests is roughly:
// (max_outstanding_requests_cost_per_process_ /
// kAvgBytesPerOutstandingRequest)
int max_outstanding_requests_cost_per_process_;
// Time of the last user gesture. Stored so that we can add a load
// flag to requests occurring soon after a gesture to indicate they
// may be because of explicit user action.
base::TimeTicks last_user_gesture_time_;
// Used during IPC message dispatching so that the handlers can get a pointer
// to the source of the message.
ResourceMessageFilter* filter_;
ResourceDispatcherHostDelegate* delegate_;
bool allow_cross_origin_auth_prompt_;
// http://crbug.com/90971 - Assists in tracking down use-after-frees on
// shutdown.
std::set<const ResourceContext*> active_resource_contexts_;
typedef std::map<GlobalRequestID,
ObserverList<ResourceMessageDelegate>*> DelegateMap;
DelegateMap delegate_map_;
scoped_ptr<ResourceScheduler> scheduler_;
DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHostImpl);
};
} // namespace content
#endif // CONTENT_BROWSER_LOADER_RESOURCE_DISPATCHER_HOST_IMPL_H_
|