1 // Copyright (c) 2011 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/ui/tab_contents/tab_contents_wrapper.h" 11 #include "content/browser/tab_contents/tab_contents.h" 12 13 InstantLoaderManager::InstantLoaderManager( 14 InstantLoaderDelegate* loader_delegate) 15 : loader_delegate_(loader_delegate), 16 current_loader_(NULL), 17 pending_loader_(NULL) { 18 } 19 20 InstantLoaderManager::~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 delete current_loader_; 32 delete pending_loader_; 33 } 34 35 InstantLoader* InstantLoaderManager::UpdateLoader( 36 TemplateURLID instant_id, 37 scoped_ptr<InstantLoader>* old_loader) { 38 InstantLoader* old_current_loader = current_loader_; 39 InstantLoader* old_pending_loader = pending_loader_; 40 41 // Determine the new loader. 42 InstantLoader* loader = NULL; 43 if (instant_id) { 44 loader = GetInstantLoader(instant_id); 45 } else { 46 if (current_loader_ && !current_loader_->template_url_id()) 47 loader = current_loader_; 48 else if (pending_loader_ && !pending_loader_->template_url_id()) 49 loader = pending_loader_; 50 else 51 loader = CreateLoader(0); 52 } 53 54 if (loader->ready()) { 55 // The loader is ready, make it the current loader no matter what. 56 current_loader_ = loader; 57 pending_loader_ = NULL; 58 } else { 59 // The loader isn't ready make it the current only if the current isn't 60 // ready. If the current is ready, then stop the current and make the new 61 // loader pending. 62 if (!current_loader_ || !current_loader_->ready()) { 63 current_loader_ = loader; 64 DCHECK(!pending_loader_); 65 } else { 66 // preview_contents() may be null for tests. 67 if (!current_loader_->template_url_id() && 68 current_loader_->preview_contents()) { 69 current_loader_->preview_contents()->tab_contents()->Stop(); 70 } 71 pending_loader_ = loader; 72 } 73 } 74 75 if (current_loader_ != old_current_loader && old_current_loader && 76 !old_current_loader->template_url_id()) { 77 old_loader->reset(old_current_loader); 78 } 79 if (pending_loader_ != old_pending_loader && old_pending_loader && 80 !old_pending_loader->template_url_id() && 81 old_pending_loader != current_loader_) { 82 DCHECK(!old_loader->get()); 83 old_loader->reset(old_pending_loader); 84 } 85 86 return active_loader(); 87 } 88 89 bool InstantLoaderManager::WillUpateChangeActiveLoader( 90 TemplateURLID instant_id) { 91 return !active_loader() || active_loader()->template_url_id() != instant_id; 92 } 93 94 void InstantLoaderManager::MakePendingCurrent( 95 scoped_ptr<InstantLoader>* old_loader) { 96 DCHECK(current_loader_); 97 DCHECK(pending_loader_); 98 99 if (!current_loader_->template_url_id()) 100 old_loader->reset(current_loader_); 101 102 current_loader_ = pending_loader_; 103 pending_loader_ = NULL; 104 } 105 106 InstantLoader* InstantLoaderManager::ReleaseCurrentLoader() { 107 DCHECK(current_loader_); 108 InstantLoader* loader = current_loader_; 109 RemoveLoaderFromInstant(current_loader_); 110 current_loader_ = NULL; 111 return loader; 112 } 113 114 void InstantLoaderManager::DestroyLoader(InstantLoader* loader) { 115 delete ReleaseLoader(loader); 116 } 117 118 InstantLoader* InstantLoaderManager::ReleaseLoader(InstantLoader* loader) { 119 DCHECK(loader == current_loader_ || loader == pending_loader_ || 120 (loader->template_url_id() && 121 instant_loaders_.find(loader->template_url_id()) != 122 instant_loaders_.end())); 123 124 if (current_loader_ == loader) 125 current_loader_ = pending_loader_; 126 127 if (pending_loader_ == loader) 128 pending_loader_ = NULL; 129 130 RemoveLoaderFromInstant(loader); 131 132 return loader; 133 } 134 135 void InstantLoaderManager::RemoveLoaderFromInstant(InstantLoader* loader) { 136 if (!loader->template_url_id()) 137 return; 138 139 Loaders::iterator i = instant_loaders_.find(loader->template_url_id()); 140 DCHECK(i != instant_loaders_.end()); 141 instant_loaders_.erase(i); 142 } 143 144 InstantLoader* InstantLoaderManager::CreateLoader(TemplateURLID id) { 145 InstantLoader* loader = new InstantLoader(loader_delegate_, id); 146 if (id) 147 instant_loaders_[id] = loader; 148 return loader; 149 } 150 151 InstantLoader* InstantLoaderManager::GetInstantLoader(TemplateURLID id) { 152 Loaders::iterator i = instant_loaders_.find(id); 153 return i == instant_loaders_.end() ? CreateLoader(id) : i->second; 154 } 155