// Copyright (c) 2011 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/instant/instant_loader_manager.h"
#include "base/logging.h"
#include "chrome/browser/instant/instant_loader.h"
#include "chrome/browser/instant/instant_loader_delegate.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "content/browser/tab_contents/tab_contents.h"
InstantLoaderManager::InstantLoaderManager(
InstantLoaderDelegate* loader_delegate)
: loader_delegate_(loader_delegate),
current_loader_(NULL),
pending_loader_(NULL) {
}
InstantLoaderManager::~InstantLoaderManager() {
for (Loaders::iterator i = instant_loaders_.begin();
i != instant_loaders_.end(); ++i) {
if (i->second == current_loader_)
current_loader_ = NULL;
if (i->second == pending_loader_)
pending_loader_ = NULL;
delete i->second;
}
instant_loaders_.clear();
delete current_loader_;
delete pending_loader_;
}
InstantLoader* InstantLoaderManager::UpdateLoader(
TemplateURLID instant_id,
scoped_ptr<InstantLoader>* old_loader) {
InstantLoader* old_current_loader = current_loader_;
InstantLoader* old_pending_loader = pending_loader_;
// Determine the new loader.
InstantLoader* loader = NULL;
if (instant_id) {
loader = GetInstantLoader(instant_id);
} else {
if (current_loader_ && !current_loader_->template_url_id())
loader = current_loader_;
else if (pending_loader_ && !pending_loader_->template_url_id())
loader = pending_loader_;
else
loader = CreateLoader(0);
}
if (loader->ready()) {
// The loader is ready, make it the current loader no matter what.
current_loader_ = loader;
pending_loader_ = NULL;
} else {
// The loader isn't ready make it the current only if the current isn't
// ready. If the current is ready, then stop the current and make the new
// loader pending.
if (!current_loader_ || !current_loader_->ready()) {
current_loader_ = loader;
DCHECK(!pending_loader_);
} else {
// preview_contents() may be null for tests.
if (!current_loader_->template_url_id() &&
current_loader_->preview_contents()) {
current_loader_->preview_contents()->tab_contents()->Stop();
}
pending_loader_ = loader;
}
}
if (current_loader_ != old_current_loader && old_current_loader &&
!old_current_loader->template_url_id()) {
old_loader->reset(old_current_loader);
}
if (pending_loader_ != old_pending_loader && old_pending_loader &&
!old_pending_loader->template_url_id() &&
old_pending_loader != current_loader_) {
DCHECK(!old_loader->get());
old_loader->reset(old_pending_loader);
}
return active_loader();
}
bool InstantLoaderManager::WillUpateChangeActiveLoader(
TemplateURLID instant_id) {
return !active_loader() || active_loader()->template_url_id() != instant_id;
}
void InstantLoaderManager::MakePendingCurrent(
scoped_ptr<InstantLoader>* old_loader) {
DCHECK(current_loader_);
DCHECK(pending_loader_);
if (!current_loader_->template_url_id())
old_loader->reset(current_loader_);
current_loader_ = pending_loader_;
pending_loader_ = NULL;
}
InstantLoader* InstantLoaderManager::ReleaseCurrentLoader() {
DCHECK(current_loader_);
InstantLoader* loader = current_loader_;
RemoveLoaderFromInstant(current_loader_);
current_loader_ = NULL;
return loader;
}
void InstantLoaderManager::DestroyLoader(InstantLoader* loader) {
delete ReleaseLoader(loader);
}
InstantLoader* InstantLoaderManager::ReleaseLoader(InstantLoader* loader) {
DCHECK(loader == current_loader_ || loader == pending_loader_ ||
(loader->template_url_id() &&
instant_loaders_.find(loader->template_url_id()) !=
instant_loaders_.end()));
if (current_loader_ == loader)
current_loader_ = pending_loader_;
if (pending_loader_ == loader)
pending_loader_ = NULL;
RemoveLoaderFromInstant(loader);
return loader;
}
void InstantLoaderManager::RemoveLoaderFromInstant(InstantLoader* loader) {
if (!loader->template_url_id())
return;
Loaders::iterator i = instant_loaders_.find(loader->template_url_id());
DCHECK(i != instant_loaders_.end());
instant_loaders_.erase(i);
}
InstantLoader* InstantLoaderManager::CreateLoader(TemplateURLID id) {
InstantLoader* loader = new InstantLoader(loader_delegate_, id);
if (id)
instant_loaders_[id] = loader;
return loader;
}
InstantLoader* InstantLoaderManager::GetInstantLoader(TemplateURLID id) {
Loaders::iterator i = instant_loaders_.find(id);
return i == instant_loaders_.end() ? CreateLoader(id) : i->second;
}