| Index: content/browser/renderer_host/resource_scheduler.cc
|
| diff --git a/content/browser/renderer_host/resource_scheduler.cc b/content/browser/renderer_host/resource_scheduler.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..669b54ecc06659619f79f4ea871ea1267a2e956b
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/resource_scheduler.cc
|
| @@ -0,0 +1,167 @@
|
| +// 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.
|
| +
|
| +#include "content/browser/renderer_host/resource_scheduler.h"
|
| +
|
| +#include "base/stl_util.h"
|
| +#include "content/browser/renderer_host/resource_loader.h"
|
| +#include "net/base/request_priority.h"
|
| +#include "net/url_request/url_request.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +ResourceScheduler::ClientId MakeClientId(int child_id, int route_id) {
|
| + return (static_cast<ResourceScheduler::ClientId>(child_id) << 32) | route_id;
|
| +}
|
| +
|
| +} // unnamed namespace
|
| +
|
| +ResourceScheduler::ResourceScheduler() {
|
| +}
|
| +
|
| +ResourceScheduler::~ResourceScheduler() {
|
| +}
|
| +
|
| +ResourceScheduler::LoadHandle* ResourceScheduler::ScheduleLoad(
|
| + int child_id,
|
| + int route_id,
|
| + int request_id,
|
| + const linked_ptr<ResourceLoader>& loader) {
|
| + if (route_id == 0) {
|
| + // <a ping> requests don't have a route_id.
|
| + loader->StartRequest();
|
| + return new UnscheduledLoadHandle(loader);
|
| + }
|
| +
|
| + ClientId client_id = MakeClientId(child_id, route_id);
|
| + CHECK(ContainsKey(client_map_, client_id));
|
| +
|
| + Client* client = client_map_[client_id];
|
| + DCHECK(!client->closed);
|
| + ScheduledLoadHandle* handle = new ScheduledLoadHandle(
|
| + client_id, request_id, loader, this);
|
| + Request request = { request_id, loader.get() };
|
| + if (loader->request()->priority() < net::MEDIUM &&
|
| + !client->in_flight_requests.empty() && !client->has_painted) {
|
| + client->pending_requests.push_back(request);
|
| + return handle;
|
| + }
|
| +
|
| + StartRequest(request, client);
|
| + return handle;
|
| +}
|
| +
|
| +void ResourceScheduler::RemoveLoad(ClientId client_id, int request_id) {
|
| + DCHECK(ContainsKey(client_map_, client_id));
|
| + Client* client = client_map_[client_id];
|
| + RequestIdSet::iterator it = client->in_flight_requests.find(request_id);
|
| + if (it == client->in_flight_requests.end()) {
|
| + bool removed = false;
|
| + RequestQueue::iterator queue_it;
|
| + for (queue_it = client->pending_requests.begin();
|
| + queue_it != client->pending_requests.end(); ++queue_it) {
|
| + if (queue_it->request_id == request_id) {
|
| + client->pending_requests.erase(queue_it);
|
| + removed = true;
|
| + break;
|
| + }
|
| + }
|
| + DCHECK(removed);
|
| + DCHECK(!ContainsKey(client->in_flight_requests, request_id));
|
| + } else {
|
| + bool erased = client->in_flight_requests.erase(request_id);
|
| + DCHECK(erased);
|
| + }
|
| +
|
| + if (client->closed) {
|
| + if (client->in_flight_requests.empty()
|
| + && client->pending_requests.empty()) {
|
| + delete client;
|
| + client_map_.erase(client_id);
|
| + }
|
| + } else if (client->in_flight_requests.empty()) {
|
| + LoadPendingRequests(client);
|
| + }
|
| +}
|
| +
|
| +void ResourceScheduler::OnCreate(int child_id, int route_id) {
|
| + ClientId client_id = MakeClientId(child_id, route_id);
|
| + DCHECK(!ContainsKey(client_map_, client_id));
|
| + client_map_[client_id] = new Client;
|
| +}
|
| +
|
| +void ResourceScheduler::OnNavigate(int child_id, int route_id) {
|
| + ClientId client_id = MakeClientId(child_id, route_id);
|
| + DCHECK(ContainsKey(client_map_, client_id));
|
| + Client* client = client_map_[client_id];
|
| + client->has_painted = false;
|
| +}
|
| +
|
| +void ResourceScheduler::OnPaint(int child_id, int route_id) {
|
| + ClientId client_id = MakeClientId(child_id, route_id);
|
| + DCHECK(ContainsKey(client_map_, client_id));
|
| + Client* client = client_map_[client_id];
|
| + if (!client->has_painted) {
|
| + client->has_painted = true;
|
| + LoadPendingRequests(client);
|
| + }
|
| +}
|
| +
|
| +void ResourceScheduler::OnDestroy(int child_id, int route_id) {
|
| + ClientId client_id = MakeClientId(child_id, route_id);
|
| + DCHECK(ContainsKey(client_map_, client_id));
|
| + Client* client = client_map_[client_id];
|
| + if (client->pending_requests.empty() && client->in_flight_requests.empty()) {
|
| + delete client;
|
| + client_map_.erase(client_id);
|
| + } else {
|
| + client->closed = true;
|
| + }
|
| +}
|
| +
|
| +void ResourceScheduler::StartRequest(Request request, Client* client) {
|
| + client->in_flight_requests.insert(request.request_id);
|
| + request.loader->StartRequest();
|
| +}
|
| +
|
| +void ResourceScheduler::LoadPendingRequests(Client* client) {
|
| + RequestQueue::iterator it;
|
| + for (it = client->pending_requests.begin();
|
| + it != client->pending_requests.end(); ++it) {
|
| + StartRequest(*it, client);
|
| + }
|
| + client->pending_requests.clear();
|
| +}
|
| +
|
| +ResourceScheduler::ScheduledLoadHandle::ScheduledLoadHandle(
|
| + ClientId client_id,
|
| + int request_id,
|
| + const linked_ptr<ResourceLoader>& loader,
|
| + ResourceScheduler* scheduler)
|
| + : client_id_(client_id),
|
| + request_id_(request_id),
|
| + loader_(loader),
|
| + scheduler_(scheduler) {
|
| +}
|
| +
|
| +ResourceScheduler::ScheduledLoadHandle::~ScheduledLoadHandle() {
|
| + scheduler_->RemoveLoad(client_id_, request_id_);
|
| +}
|
| +
|
| +ResourceScheduler::UnscheduledLoadHandle::UnscheduledLoadHandle(
|
| + const linked_ptr<ResourceLoader>& loader)
|
| + : loader_(loader) {
|
| +}
|
| +
|
| +ResourceScheduler::UnscheduledLoadHandle::~UnscheduledLoadHandle() {
|
| +}
|
| +
|
| +ResourceScheduler::Client::Client()
|
| + : has_painted(false),
|
| + closed(false) {
|
| +}
|
| +
|
| +} // namespace content
|
|
|