instant_loader_manager.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/instant/instant_loader_manager.h"
6
7#include "base/logging.h"
8#include "chrome/browser/instant/instant_loader.h"
9#include "chrome/browser/instant/instant_loader_delegate.h"
10#include "chrome/browser/tab_contents/tab_contents.h"
11#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
12
13InstantLoaderManager::InstantLoaderManager(
14    InstantLoaderDelegate* loader_delegate)
15    : loader_delegate_(loader_delegate),
16      current_loader_(NULL),
17      pending_loader_(NULL) {
18}
19
20InstantLoaderManager::~InstantLoaderManager() {
21  for (Loaders::iterator i = instant_loaders_.begin();
22       i != instant_loaders_.end(); ++i) {
23    if (i->second == current_loader_)
24      current_loader_ = NULL;
25    if (i->second == pending_loader_)
26      pending_loader_ = NULL;
27    delete i->second;
28  }
29  instant_loaders_.clear();
30
31  if (current_loader_)
32    delete current_loader_;
33  if (pending_loader_)
34    delete pending_loader_;
35}
36
37InstantLoader* InstantLoaderManager::UpdateLoader(
38    TemplateURLID instant_id,
39    scoped_ptr<InstantLoader>* old_loader) {
40  InstantLoader* old_current_loader = current_loader_;
41  InstantLoader* old_pending_loader = pending_loader_;
42
43  // Determine the new loader.
44  InstantLoader* loader = NULL;
45  if (instant_id) {
46    loader = GetInstantLoader(instant_id);
47  } else {
48    if (current_loader_ && !current_loader_->template_url_id())
49      loader = current_loader_;
50    else if (pending_loader_ && !pending_loader_->template_url_id())
51      loader = pending_loader_;
52    else
53      loader = CreateLoader(0);
54  }
55
56  if (loader->ready()) {
57    // The loader is ready, make it the current loader no matter what.
58    current_loader_ = loader;
59    pending_loader_ = NULL;
60  } else {
61    // The loader isn't ready make it the current only if the current isn't
62    // ready. If the current is ready, then stop the current and make the new
63    // loader pending.
64    if (!current_loader_ || !current_loader_->ready()) {
65      current_loader_ = loader;
66      DCHECK(!pending_loader_);
67    } else {
68      // preview_contents() may be null for tests.
69      if (!current_loader_->template_url_id() &&
70          current_loader_->preview_contents()) {
71        current_loader_->preview_contents()->tab_contents()->Stop();
72      }
73      pending_loader_ = loader;
74    }
75  }
76
77  if (current_loader_ != old_current_loader && old_current_loader &&
78      !old_current_loader->template_url_id()) {
79    old_loader->reset(old_current_loader);
80  }
81  if (pending_loader_ != old_pending_loader && old_pending_loader &&
82      !old_pending_loader->template_url_id()) {
83    DCHECK(!old_loader->get());
84    old_loader->reset(old_pending_loader);
85  }
86
87  return active_loader();
88}
89
90bool InstantLoaderManager::WillUpateChangeActiveLoader(
91    TemplateURLID instant_id) {
92  return !active_loader() || active_loader()->template_url_id() != instant_id;
93}
94
95void InstantLoaderManager::MakePendingCurrent(
96    scoped_ptr<InstantLoader>* old_loader) {
97  DCHECK(current_loader_);
98  DCHECK(pending_loader_);
99
100  if (!current_loader_->template_url_id())
101    old_loader->reset(current_loader_);
102
103  current_loader_ = pending_loader_;
104  pending_loader_ = NULL;
105}
106
107InstantLoader* InstantLoaderManager::ReleaseCurrentLoader() {
108  DCHECK(current_loader_);
109  InstantLoader* loader = current_loader_;
110  RemoveLoaderFromInstant(current_loader_);
111  current_loader_ = NULL;
112  return loader;
113}
114
115void InstantLoaderManager::DestroyLoader(InstantLoader* loader) {
116  delete ReleaseLoader(loader);
117}
118
119InstantLoader* InstantLoaderManager::ReleaseLoader(InstantLoader* loader) {
120  DCHECK(loader == current_loader_ || loader == pending_loader_ ||
121         (loader->template_url_id() &&
122          instant_loaders_.find(loader->template_url_id()) !=
123          instant_loaders_.end()));
124
125  if (current_loader_ == loader)
126    current_loader_ = pending_loader_;
127
128  if (pending_loader_ == loader)
129    pending_loader_ = NULL;
130
131  RemoveLoaderFromInstant(loader);
132
133  return loader;
134}
135
136void InstantLoaderManager::RemoveLoaderFromInstant(InstantLoader* loader) {
137  if (!loader->template_url_id())
138    return;
139
140  Loaders::iterator i = instant_loaders_.find(loader->template_url_id());
141  DCHECK(i != instant_loaders_.end());
142  instant_loaders_.erase(i);
143}
144
145InstantLoader* InstantLoaderManager::CreateLoader(TemplateURLID id) {
146  InstantLoader* loader = new InstantLoader(loader_delegate_, id);
147  if (id)
148    instant_loaders_[id] = loader;
149  return loader;
150}
151
152InstantLoader* InstantLoaderManager::GetInstantLoader(TemplateURLID id) {
153  Loaders::iterator i = instant_loaders_.find(id);
154  return i == instant_loaders_.end() ? CreateLoader(id) : i->second;
155}
156