blob: cabb35b44b09a00dda368857adb47598aba471c8 [file] [log] [blame]
// 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 "chrome/browser/prerender/prerender_tracker.h"
#include "base/bind.h"
#include "base/logging.h"
#include "chrome/browser/prerender/prerender_pending_swap_throttle.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
using content::BrowserThread;
namespace prerender {
PrerenderTracker::PrerenderTracker() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
PrerenderTracker::~PrerenderTracker() {
}
bool PrerenderTracker::IsPendingSwapRequestOnIOThread(
int render_process_id, int render_frame_id, const GURL& url) const {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ChildRouteIdPair render_frame_route_id_pair(
render_process_id, render_frame_id);
PendingSwapThrottleMap::const_iterator it =
pending_swap_throttle_map_.find(render_frame_route_id_pair);
return (it != pending_swap_throttle_map_.end() && it->second.url == url);
}
void PrerenderTracker::AddPendingSwapThrottleOnIOThread(
int render_process_id,
int render_frame_id,
const GURL& url,
const base::WeakPtr<PrerenderPendingSwapThrottle>& throttle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ChildRouteIdPair render_frame_route_id_pair(
render_process_id, render_frame_id);
PendingSwapThrottleMap::iterator it =
pending_swap_throttle_map_.find(render_frame_route_id_pair);
DCHECK(it != pending_swap_throttle_map_.end());
if (it == pending_swap_throttle_map_.end())
return;
CHECK(!it->second.throttle);
it->second.throttle = throttle;
}
void PrerenderTracker::AddPrerenderPendingSwapOnIOThread(
const ChildRouteIdPair& render_frame_route_id_pair,
const GURL& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
std::pair<PendingSwapThrottleMap::iterator, bool> insert_result =
pending_swap_throttle_map_.insert(std::make_pair(
render_frame_route_id_pair, PendingSwapThrottleData(url)));
DCHECK(insert_result.second);
}
void PrerenderTracker::RemovePrerenderPendingSwapOnIOThread(
const ChildRouteIdPair& render_frame_route_id_pair,
bool swap_successful) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
PendingSwapThrottleMap::iterator it =
pending_swap_throttle_map_.find(render_frame_route_id_pair);
DCHECK(it != pending_swap_throttle_map_.end());
// Cancel or resume all throttled resources.
if (it->second.throttle) {
if (swap_successful)
it->second.throttle->Cancel();
else
it->second.throttle->Resume();
}
pending_swap_throttle_map_.erase(render_frame_route_id_pair);
}
void PrerenderTracker::AddPrerenderPendingSwap(
const ChildRouteIdPair& render_frame_route_id_pair,
const GURL& url) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PrerenderTracker::AddPrerenderPendingSwapOnIOThread,
base::Unretained(this), render_frame_route_id_pair, url));
}
void PrerenderTracker::RemovePrerenderPendingSwap(
const ChildRouteIdPair& render_frame_route_id_pair,
bool swap_successful) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PrerenderTracker::RemovePrerenderPendingSwapOnIOThread,
base::Unretained(this), render_frame_route_id_pair,
swap_successful));
}
PrerenderTracker::PendingSwapThrottleData::PendingSwapThrottleData(
const GURL& swap_url)
: url(swap_url) {
}
PrerenderTracker::PendingSwapThrottleData::~PendingSwapThrottleData() {
}
scoped_refptr<PrerenderCookieStore>
PrerenderTracker::GetPrerenderCookieStoreForRenderProcess(
int process_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
PrerenderCookieStoreMap::const_iterator it =
prerender_cookie_store_map_.find(process_id);
if (it == prerender_cookie_store_map_.end())
return NULL;
return it->second;
}
void PrerenderTracker::OnCookieChangedForURL(
int process_id,
net::CookieMonster* cookie_monster,
const GURL& url) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
// We only care about cookie changes by non-prerender tabs, since only those
// get applied to the underlying cookie store. Therefore, if a cookie change
// originated from a prerender, there is nothing to do.
if (ContainsKey(prerender_cookie_store_map_, process_id))
return;
// Since the cookie change did not come from a prerender, broadcast it too
// all prerenders so that they can be cancelled if there is a conflict.
for (PrerenderCookieStoreMap::iterator it =
prerender_cookie_store_map_.begin();
it != prerender_cookie_store_map_.end();
++it) {
it->second->OnCookieChangedForURL(cookie_monster, url);
}
}
void PrerenderTracker::RemovePrerenderCookieStoreOnIOThread(int process_id,
bool was_swapped) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
PrerenderCookieStoreMap::iterator it =
prerender_cookie_store_map_.find(process_id);
if (it == prerender_cookie_store_map_.end())
return;
std::vector<GURL> cookie_change_urls;
if (was_swapped)
it->second->ApplyChanges(&cookie_change_urls);
scoped_refptr<net::CookieMonster> cookie_monster(
it->second->default_cookie_monster());
prerender_cookie_store_map_.erase(it);
// For each cookie updated by ApplyChanges, we need to call
// OnCookieChangedForURL so that any potentially conflicting prerenders
// will be aborted.
for (std::vector<GURL>::const_iterator url_it = cookie_change_urls.begin();
url_it != cookie_change_urls.end();
++url_it) {
OnCookieChangedForURL(process_id, cookie_monster, *url_it);
}
}
void PrerenderTracker::AddPrerenderCookieStoreOnIOThread(
int process_id,
scoped_refptr<net::URLRequestContextGetter> request_context,
const base::Closure& cookie_conflict_cb) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
DCHECK(request_context != NULL);
net::CookieMonster* cookie_monster =
request_context->GetURLRequestContext()->cookie_store()->
GetCookieMonster();
DCHECK(cookie_monster != NULL);
bool exists = (prerender_cookie_store_map_.find(process_id) !=
prerender_cookie_store_map_.end());
DCHECK(!exists);
if (exists)
return;
prerender_cookie_store_map_[process_id] =
new PrerenderCookieStore(make_scoped_refptr(cookie_monster),
cookie_conflict_cb);
}
} // namespace prerender