| // 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; |
| } |