Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prerender/prerender_link_manager.h" | 5 #include "chrome/browser/prerender/prerender_link_manager.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <set> | |
| 8 #include <utility> | 9 #include <utility> |
| 9 | 10 |
| 10 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 11 #include "chrome/browser/prerender/prerender_contents.h" | 12 #include "chrome/browser/prerender/prerender_contents.h" |
| 12 #include "chrome/browser/prerender/prerender_handle.h" | 13 #include "chrome/browser/prerender/prerender_handle.h" |
| 13 #include "chrome/browser/prerender/prerender_manager.h" | 14 #include "chrome/browser/prerender/prerender_manager.h" |
| 14 #include "chrome/browser/prerender/prerender_manager_factory.h" | 15 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/common/prerender_messages.h" | 17 #include "chrome/common/prerender_messages.h" |
| 17 #include "content/public/browser/render_process_host.h" | 18 #include "content/public/browser/render_process_host.h" |
| 18 #include "content/public/browser/render_view_host.h" | 19 #include "content/public/browser/render_view_host.h" |
| 19 #include "content/public/browser/session_storage_namespace.h" | 20 #include "content/public/browser/session_storage_namespace.h" |
| 20 #include "content/public/common/referrer.h" | 21 #include "content/public/common/referrer.h" |
| 21 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
| 22 #include "ui/gfx/size.h" | 23 #include "ui/gfx/size.h" |
| 23 | 24 |
| 25 using base::TimeDelta; | |
| 26 using base::TimeTicks; | |
| 24 using content::RenderViewHost; | 27 using content::RenderViewHost; |
| 25 using content::SessionStorageNamespace; | 28 using content::SessionStorageNamespace; |
| 26 | 29 |
| 27 namespace { | 30 namespace { |
| 28 | 31 |
| 29 void Send(int child_id, IPC::Message* raw_message) { | 32 void Send(int child_id, IPC::Message* raw_message) { |
| 30 using content::RenderProcessHost; | 33 using content::RenderProcessHost; |
| 31 scoped_ptr<IPC::Message> own_message(raw_message); | 34 scoped_ptr<IPC::Message> own_message(raw_message); |
| 32 | 35 |
| 33 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); | 36 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); |
| 34 if (!render_process_host) | 37 if (!render_process_host) |
| 35 return; | 38 return; |
| 36 render_process_host->Send(own_message.release()); | 39 render_process_host->Send(own_message.release()); |
| 37 } | 40 } |
| 38 | 41 |
| 39 } // namespace | 42 } // namespace |
| 40 | 43 |
| 41 namespace prerender { | 44 namespace prerender { |
| 42 | 45 |
| 43 PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager) | 46 PrerenderLinkManager::PrerenderLinkManager(PrerenderManager* manager) |
| 44 : manager_(manager) { | 47 : has_shutdown_(false), |
| 48 manager_(manager) { | |
| 45 } | 49 } |
| 46 | 50 |
| 47 PrerenderLinkManager::~PrerenderLinkManager() { | 51 PrerenderLinkManager::~PrerenderLinkManager() { |
| 48 for (IdPairToPrerenderHandleMap::iterator it = ids_to_handle_map_.begin(); | 52 for (std::list<Prerender>::iterator i = prerenders_.begin(); |
| 49 it != ids_to_handle_map_.end(); | 53 i != prerenders_.end(); ++i) { |
| 50 ++it) { | 54 if (i->handle) { |
| 51 PrerenderHandle* prerender_handle = it->second; | 55 DCHECK(!i->handle->IsPrerendering()) |
| 52 DCHECK(!prerender_handle->IsPrerendering()) | 56 << "All running prerenders should stop at the same time as the " |
| 53 << "All running prerenders should stop at the same time as the " | 57 << "PrerenderManager."; |
| 54 << "PrerenderManager."; | 58 delete i->handle; |
| 55 delete prerender_handle; | 59 i->handle = 0; |
| 56 } | 60 } |
| 57 } | 61 } |
| 58 | 62 } |
| 59 bool PrerenderLinkManager::OnAddPrerender(int child_id, | 63 |
| 64 void PrerenderLinkManager::OnAddPrerender(int launcher_child_id, | |
| 60 int prerender_id, | 65 int prerender_id, |
| 61 const GURL& url, | 66 const GURL& url, |
| 62 const content::Referrer& referrer, | 67 const content::Referrer& referrer, |
| 63 const gfx::Size& size, | 68 const gfx::Size& size, |
| 64 int render_view_route_id) { | 69 int render_view_route_id) { |
| 65 DVLOG(2) << "OnAddPrerender, child_id = " << child_id | 70 Prerender prerender(launcher_child_id, prerender_id, url, referrer, size, |
| 66 << ", prerender_id = " << prerender_id | 71 render_view_route_id, manager_->GetCurrentTimeTicks()); |
| 67 << ", url = " << url.spec(); | 72 prerenders_.push_back(prerender); |
| 68 DVLOG(3) << "... referrer url = " << referrer.url.spec() | 73 StartPrerenders(); |
| 69 << ", size = (" << size.width() << ", " << size.height() << ")" | |
| 70 << ", render_view_route_id = " << render_view_route_id; | |
| 71 | |
| 72 | |
| 73 PrerenderHandle* prerender_handle = | |
| 74 manager_->AddPrerenderFromLinkRelPrerender( | |
| 75 child_id, render_view_route_id, url, referrer, size); | |
| 76 if (!prerender_handle) | |
| 77 return false; | |
| 78 | |
| 79 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); | |
| 80 DCHECK_EQ(0u, ids_to_handle_map_.count(child_and_prerender_id)); | |
| 81 ids_to_handle_map_[child_and_prerender_id] = prerender_handle; | |
| 82 | |
| 83 // If we are given a prerender that is already prerendering, we have missed | |
| 84 // the start event. | |
| 85 if (prerender_handle->IsPrerendering()) | |
| 86 OnPrerenderStart(prerender_handle); | |
| 87 prerender_handle->SetObserver(this); | |
| 88 return true; | |
| 89 } | 74 } |
| 90 | 75 |
| 91 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { | 76 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { |
| 92 DVLOG(2) << "OnCancelPrerender, child_id = " << child_id | 77 Prerender* prerender = FindByLauncherChildIdAndPrerenderId(child_id, |
| 93 << ", prerender_id = " << prerender_id; | 78 prerender_id); |
| 94 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); | 79 if (!prerender) |
| 95 IdPairToPrerenderHandleMap::iterator id_to_handle_iter = | 80 return; |
| 96 ids_to_handle_map_.find(child_and_prerender_id); | 81 |
| 97 if (id_to_handle_iter == ids_to_handle_map_.end()) { | 82 // Remove the handle from the PrerenderLinkManager before we cancel this |
| 98 DVLOG(5) << "... canceling a prerender that doesn't exist."; | 83 // prerender, to avoid reentering the PrerenderLinkManager, sending events to |
| 99 return; | 84 // the underlying prerender and making a second erase. |
| 100 } | 85 scoped_ptr<PrerenderHandle> own_prerender_handle(prerender->handle); |
| 101 | 86 prerender->handle = NULL; |
| 102 scoped_ptr<PrerenderHandle> prerender_handle(id_to_handle_iter->second); | 87 RemovePrerender(prerender); |
| 103 ids_to_handle_map_.erase(id_to_handle_iter); | 88 |
| 104 prerender_handle->OnCancel(); | 89 if (own_prerender_handle) |
| 105 | 90 own_prerender_handle->OnCancel(); |
| 106 // Because OnCancel() can remove the prerender from the map, we need to | 91 |
| 107 // consider our iterator invalid. | 92 StartPrerenders(); |
| 108 id_to_handle_iter = ids_to_handle_map_.find(child_and_prerender_id); | |
| 109 if (id_to_handle_iter != ids_to_handle_map_.end()) | |
| 110 RemovePrerender(id_to_handle_iter); | |
| 111 } | 93 } |
| 112 | 94 |
| 113 void PrerenderLinkManager::OnAbandonPrerender(int child_id, int prerender_id) { | 95 void PrerenderLinkManager::OnAbandonPrerender(int child_id, int prerender_id) { |
| 114 DVLOG(2) << "OnAbandonPrerender, child_id = " << child_id | 96 Prerender* prerender = FindByLauncherChildIdAndPrerenderId(child_id, |
| 115 << ", prerender_id = " << prerender_id; | 97 prerender_id); |
| 116 const ChildAndPrerenderIdPair child_and_prerender_id(child_id, prerender_id); | 98 if (!prerender) |
| 117 IdPairToPrerenderHandleMap::iterator id_to_handle_iter = | 99 return; |
| 118 ids_to_handle_map_.find(child_and_prerender_id); | 100 |
| 119 if (id_to_handle_iter == ids_to_handle_map_.end()) | 101 if (!prerender->handle) { |
| 120 return; | 102 RemovePrerender(prerender); |
| 121 PrerenderHandle* prerender_handle = id_to_handle_iter->second; | 103 return; |
| 122 prerender_handle->OnNavigateAway(); | 104 } |
| 105 | |
| 106 prerender->handle->OnNavigateAway(); | |
| 107 DCHECK(prerender->handle); | |
| 108 | |
| 109 // If the prerender is not running, remove it from the list so it does not | |
| 110 // leak. If it is running, it will send a cancel event when it stops which | |
| 111 // will remove it. | |
| 112 if (!prerender->handle->IsPrerendering()) | |
| 113 RemovePrerender(prerender); | |
| 123 } | 114 } |
| 124 | 115 |
| 125 void PrerenderLinkManager::OnChannelClosing(int child_id) { | 116 void PrerenderLinkManager::OnChannelClosing(int child_id) { |
| 126 DVLOG(2) << "OnChannelClosing, child id = " << child_id; | 117 std::list<Prerender>::iterator next = prerenders_.begin(); |
| 127 const ChildAndPrerenderIdPair child_and_minimum_prerender_id( | 118 while (next != prerenders_.end()) { |
| 128 child_id, std::numeric_limits<int>::min()); | 119 std::list<Prerender>::iterator it = next; |
| 129 const ChildAndPrerenderIdPair child_and_maximum_prerender_id( | |
| 130 child_id, std::numeric_limits<int>::max()); | |
| 131 | |
| 132 IdPairToPrerenderHandleMap::iterator | |
| 133 it = ids_to_handle_map_.lower_bound(child_and_minimum_prerender_id); | |
| 134 IdPairToPrerenderHandleMap::iterator | |
| 135 end = ids_to_handle_map_.upper_bound(child_and_maximum_prerender_id); | |
| 136 while (it != end) { | |
| 137 IdPairToPrerenderHandleMap::iterator next = it; | |
| 138 ++next; | 120 ++next; |
| 139 | 121 |
| 140 size_t size_before_abandon = ids_to_handle_map_.size(); | 122 if (child_id != it->launcher_child_id) |
| 141 OnAbandonPrerender(child_id, it->first.second); | 123 continue; |
| 142 DCHECK_EQ(size_before_abandon, ids_to_handle_map_.size()); | 124 |
| 143 RemovePrerender(it); | 125 const size_t running_prerender_count = CountRunningPrerenders(); |
| 144 | 126 OnAbandonPrerender(child_id, it->prerender_id); |
| 145 it = next; | 127 DCHECK_EQ(running_prerender_count, CountRunningPrerenders()); |
| 146 } | 128 } |
| 129 } | |
| 130 | |
| 131 PrerenderLinkManager::Prerender::Prerender(int launcher_child_id, | |
| 132 int prerender_id, | |
| 133 const GURL& url, | |
| 134 const content::Referrer& referrer, | |
| 135 const gfx::Size& size, | |
| 136 int render_view_route_id, | |
| 137 TimeTicks creation_time) | |
| 138 : launcher_child_id(launcher_child_id), | |
| 139 prerender_id(prerender_id), | |
| 140 url(url), | |
| 141 referrer(referrer), | |
| 142 size(size), | |
| 143 render_view_route_id(render_view_route_id), | |
| 144 creation_time(creation_time), | |
| 145 handle(NULL) { | |
| 146 } | |
| 147 | |
| 148 PrerenderLinkManager::Prerender::~Prerender() { | |
| 149 DCHECK_EQ(static_cast<PrerenderHandle*>(NULL), handle); | |
|
mmenke
2012/12/28 18:25:33
Think this is non-intuitive enough to be worth a c
gavinp
2012/12/28 19:53:46
Done.
| |
| 147 } | 150 } |
| 148 | 151 |
| 149 bool PrerenderLinkManager::IsEmpty() const { | 152 bool PrerenderLinkManager::IsEmpty() const { |
| 150 return ids_to_handle_map_.empty(); | 153 return prerenders_.empty(); |
| 151 } | 154 } |
| 152 | 155 |
| 153 void PrerenderLinkManager::RemovePrerender( | 156 size_t PrerenderLinkManager::CountRunningPrerenders() const { |
| 154 const IdPairToPrerenderHandleMap::iterator& id_to_handle_iter) { | 157 size_t retval = 0; |
| 155 PrerenderHandle* prerender_handle = id_to_handle_iter->second; | 158 for (std::list<Prerender>::const_iterator i = prerenders_.begin(); |
| 156 delete prerender_handle; | 159 i != prerenders_.end(); ++i) { |
| 157 ids_to_handle_map_.erase(id_to_handle_iter); | 160 if (i->handle && i->handle->IsPrerendering()) |
| 158 } | 161 ++retval; |
| 159 | 162 } |
| 160 PrerenderLinkManager::IdPairToPrerenderHandleMap::iterator | 163 return retval; |
| 161 PrerenderLinkManager::FindPrerenderHandle( | 164 } |
| 162 PrerenderHandle* prerender_handle) { | 165 |
| 163 for (IdPairToPrerenderHandleMap::iterator it = ids_to_handle_map_.begin(); | 166 void PrerenderLinkManager::StartPrerenders() { |
|
mmenke
2012/12/28 18:25:33
Some thoughts on this change (No need to address t
gavinp
2012/12/28 19:53:46
Noted.
| |
| 164 it != ids_to_handle_map_.end(); ++it) { | 167 if (has_shutdown_) |
| 165 if (it->second == prerender_handle) | 168 return; |
| 166 return it; | 169 |
| 167 } | 170 std::set<std::pair<int, int> > launcher_and_prerender_id_set; |
|
mmenke
2012/12/28 18:25:33
This is only used for sanity checking - are compil
gavinp
2012/12/28 19:53:46
I doubt compilers are that smart. I'm removing it.
mmenke
2012/12/28 20:15:13
optional: Actually...you could do something like:
gavinp
2012/12/28 20:54:21
Done. Also found I'd left a std::pair sitting arou
| |
| 168 return ids_to_handle_map_.end(); | 171 |
| 172 size_t added_prerender_count = 0; | |
|
mmenke
2012/12/28 18:25:33
nit: Think "running" or "started" would be cleare
gavinp
2012/12/28 19:53:46
total_started_prerender_count avoided confusion I
| |
| 173 std::multiset<std::pair<int, int> > | |
| 174 running_launcher_and_render_view_route_set; | |
|
mmenke
2012/12/28 18:25:33
optional: You may want to use a map here instead
mmenke
2012/12/28 18:25:33
optional: May want to just pluralize this and rem
mmenke
2012/12/28 18:32:39
This is one of those time-of-day comments, btw - i
gavinp
2012/12/28 19:53:46
I liked the name change, but I can't bear to move
mmenke
2012/12/28 20:15:13
I'm content with keeping it as-is. If I had parti
| |
| 175 | |
| 176 // Scan the list, counting how many prerenders have handles (and so were added | |
| 177 // to the PrerenderManager). The count is done for the system as a whole, and | |
| 178 // also per launcher. | |
| 179 for (std::list<Prerender>::iterator i = prerenders_.begin(); | |
| 180 i != prerenders_.end(); ++i) { | |
| 181 if (i->handle) { | |
| 182 ++added_prerender_count; | |
| 183 std::pair<int, int> launcher_and_render_view_route( | |
| 184 i->launcher_child_id, i->render_view_route_id); | |
| 185 running_launcher_and_render_view_route_set.insert( | |
| 186 launcher_and_render_view_route); | |
| 187 DCHECK_GE(manager_->config().max_link_concurrency_per_launcher, | |
| 188 running_launcher_and_render_view_route_set.count( | |
| 189 launcher_and_render_view_route)); | |
| 190 } | |
| 191 | |
| 192 std::pair<int, int> launcher_and_prerender_id(i->launcher_child_id, | |
| 193 i->prerender_id); | |
| 194 DCHECK_EQ(0u, | |
| 195 launcher_and_prerender_id_set.count(launcher_and_prerender_id)); | |
| 196 launcher_and_prerender_id_set.insert(launcher_and_prerender_id); | |
| 197 } | |
| 198 DCHECK_GE(manager_->config().max_link_concurrency, added_prerender_count); | |
| 199 DCHECK_LE(CountRunningPrerenders(), added_prerender_count); | |
| 200 | |
| 201 TimeTicks now = manager_->GetCurrentTimeTicks(); | |
| 202 | |
| 203 // Scan the list again, starting prerenders as our counts allow. | |
| 204 std::list<Prerender>::iterator next = prerenders_.begin(); | |
| 205 while (next != prerenders_.end()) { | |
| 206 std::list<Prerender>::iterator i = next; | |
| 207 ++next; | |
| 208 | |
| 209 if (added_prerender_count >= manager_->config().max_link_concurrency || | |
| 210 added_prerender_count >= prerenders_.size()) { | |
| 211 // The system is already at its prerender concurrency limit. | |
| 212 return; | |
| 213 } | |
| 214 | |
| 215 if (i->handle) { | |
| 216 // This prerender has already been added to the prerender manager. | |
| 217 continue; | |
| 218 } | |
| 219 | |
| 220 std::pair<int, int> launcher_and_render_view_route( | |
| 221 i->launcher_child_id, i->render_view_route_id); | |
| 222 if (manager_->config().max_link_concurrency_per_launcher <= | |
| 223 running_launcher_and_render_view_route_set.count( | |
| 224 launcher_and_render_view_route)) { | |
| 225 // This prerender's launcher is already at its limit. | |
| 226 continue; | |
| 227 } | |
| 228 | |
| 229 TimeDelta prerender_age = now - i->creation_time; | |
| 230 if (prerender_age >= manager_->config().max_wait_to_launch) { | |
|
mmenke
2012/12/28 18:25:33
This should go before checking the launcher concur
gavinp
2012/12/28 19:53:46
Done.
| |
| 231 // This prerender waited too long in the queue before launching. | |
| 232 prerenders_.erase(i); | |
| 233 continue; | |
| 234 } | |
| 235 | |
| 236 PrerenderHandle* handle = manager_->AddPrerenderFromLinkRelPrerender( | |
| 237 i->launcher_child_id, i->render_view_route_id, | |
| 238 i->url, i->referrer, i->size); | |
| 239 if (!handle) { | |
| 240 // This prerender couldn't be launched, it's gone. | |
| 241 prerenders_.erase(i); | |
| 242 continue; | |
| 243 } | |
| 244 | |
| 245 // We have successfully started a new prerender. | |
| 246 i->handle = handle; | |
| 247 ++added_prerender_count; | |
| 248 handle->SetObserver(this); | |
| 249 if (handle->IsPrerendering()) | |
| 250 OnPrerenderStart(handle); | |
| 251 | |
| 252 running_launcher_and_render_view_route_set.insert( | |
| 253 launcher_and_render_view_route); | |
| 254 } | |
| 255 } | |
| 256 | |
| 257 PrerenderLinkManager::Prerender* | |
| 258 PrerenderLinkManager::FindByLauncherChildIdAndPrerenderId(int launcher_child_id, | |
| 259 int prerender_id) { | |
| 260 for (std::list<Prerender>::iterator i = prerenders_.begin(); | |
| 261 i != prerenders_.end(); ++i) { | |
| 262 if (launcher_child_id == i->launcher_child_id && | |
| 263 prerender_id == i->prerender_id) { | |
| 264 return &(*i); | |
| 265 } | |
| 266 } | |
| 267 return NULL; | |
| 268 } | |
| 269 | |
| 270 PrerenderLinkManager::Prerender* | |
| 271 PrerenderLinkManager::FindByPrerenderHandle(PrerenderHandle* prerender_handle) { | |
| 272 DCHECK(prerender_handle); | |
| 273 for (std::list<Prerender>::iterator i = prerenders_.begin(); | |
| 274 i != prerenders_.end(); ++i) { | |
| 275 if (prerender_handle == i->handle) | |
| 276 return &(*i); | |
| 277 } | |
| 278 return NULL; | |
| 279 } | |
| 280 | |
| 281 void PrerenderLinkManager::RemovePrerender(Prerender* prerender) { | |
| 282 for (std::list<Prerender>::iterator i = prerenders_.begin(); | |
| 283 i != prerenders_.end(); ++i) { | |
| 284 if (&(*i) == prerender) { | |
| 285 scoped_ptr<PrerenderHandle> own_handle(i->handle); | |
| 286 i->handle = NULL; | |
| 287 prerenders_.erase(i); | |
| 288 return; | |
| 289 } | |
| 290 } | |
| 291 NOTREACHED(); | |
| 292 } | |
| 293 | |
| 294 void PrerenderLinkManager::Shutdown() { | |
| 295 has_shutdown_ = true; | |
| 169 } | 296 } |
| 170 | 297 |
| 171 // In practice, this is always called from either | 298 // In practice, this is always called from either |
| 172 // PrerenderLinkManager::OnAddPrerender in the regular case, or in the pending | 299 // PrerenderLinkManager::OnAddPrerender in the regular case, or in the pending |
| 173 // prerender case, from PrerenderHandle::AdoptPrerenderDataFrom. | 300 // prerender case, from PrerenderHandle::AdoptPrerenderDataFrom. |
| 174 void PrerenderLinkManager::OnPrerenderStart( | 301 void PrerenderLinkManager::OnPrerenderStart( |
| 175 PrerenderHandle* prerender_handle) { | 302 PrerenderHandle* prerender_handle) { |
| 176 IdPairToPrerenderHandleMap::iterator it = | 303 Prerender* prerender = FindByPrerenderHandle(prerender_handle); |
| 177 FindPrerenderHandle(prerender_handle); | 304 if (!prerender) |
| 178 DCHECK(it != ids_to_handle_map_.end()); | 305 return; |
| 179 const int child_id = it->first.first; | 306 Send(prerender->launcher_child_id, |
| 180 const int prerender_id = it->first.second; | 307 new PrerenderMsg_OnPrerenderStart(prerender->prerender_id)); |
| 181 | |
| 182 Send(child_id, new PrerenderMsg_OnPrerenderStart(prerender_id)); | |
| 183 } | 308 } |
| 184 | 309 |
| 185 void PrerenderLinkManager::OnPrerenderAddAlias( | 310 void PrerenderLinkManager::OnPrerenderAddAlias( |
| 186 PrerenderHandle* prerender_handle, | 311 PrerenderHandle* prerender_handle, |
| 187 const GURL& alias_url) { | 312 const GURL& alias_url) { |
| 188 IdPairToPrerenderHandleMap::iterator it = | 313 Prerender* prerender = FindByPrerenderHandle(prerender_handle); |
| 189 FindPrerenderHandle(prerender_handle); | 314 if (!prerender) |
| 190 if (it == ids_to_handle_map_.end()) | |
| 191 return; | 315 return; |
| 192 const int child_id = it->first.first; | 316 Send(prerender->launcher_child_id, |
| 193 const int prerender_id = it->first.second; | 317 new PrerenderMsg_OnPrerenderAddAlias(prerender->prerender_id, |
| 194 | 318 alias_url)); |
| 195 Send(child_id, new PrerenderMsg_OnPrerenderAddAlias(prerender_id, alias_url)); | |
| 196 } | 319 } |
| 197 | 320 |
| 198 void PrerenderLinkManager::OnPrerenderStop( | 321 void PrerenderLinkManager::OnPrerenderStop( |
| 199 PrerenderHandle* prerender_handle) { | 322 PrerenderHandle* prerender_handle) { |
| 200 IdPairToPrerenderHandleMap::iterator it = | 323 Prerender* prerender = FindByPrerenderHandle(prerender_handle); |
| 201 FindPrerenderHandle(prerender_handle); | 324 if (!prerender) |
| 202 if (it == ids_to_handle_map_.end()) | |
| 203 return; | 325 return; |
| 204 const int child_id = it->first.first; | |
| 205 const int prerender_id = it->first.second; | |
| 206 | 326 |
| 207 Send(child_id, new PrerenderMsg_OnPrerenderStop(prerender_id)); | 327 Send(prerender->launcher_child_id, |
| 208 RemovePrerender(it); | 328 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id)); |
| 329 RemovePrerender(prerender); | |
| 330 StartPrerenders(); | |
| 209 } | 331 } |
| 210 | 332 |
| 211 } // namespace prerender | 333 } // namespace prerender |
| OLD | NEW |