| 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 <functional> | 7 #include <functional> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | |
| 11 #include <utility> | 10 #include <utility> |
| 12 | 11 |
| 13 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/metrics/field_trial.h" | |
| 15 #include "chrome/browser/prerender/prerender_contents.h" | 13 #include "chrome/browser/prerender/prerender_contents.h" |
| 16 #include "chrome/browser/prerender/prerender_handle.h" | 14 #include "chrome/browser/prerender/prerender_handle.h" |
| 17 #include "chrome/browser/prerender/prerender_manager.h" | 15 #include "chrome/browser/prerender/prerender_manager.h" |
| 18 #include "chrome/browser/prerender/prerender_manager_factory.h" | 16 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 19 #include "chrome/browser/profiles/profile.h" | 17 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/common/prerender_messages.h" | 18 #include "chrome/common/prerender_messages.h" |
| 21 #include "chrome/common/prerender_types.h" | |
| 22 #include "content/public/browser/render_process_host.h" | 19 #include "content/public/browser/render_process_host.h" |
| 23 #include "content/public/browser/render_view_host.h" | 20 #include "content/public/browser/render_view_host.h" |
| 24 #include "content/public/browser/session_storage_namespace.h" | 21 #include "content/public/browser/session_storage_namespace.h" |
| 25 #include "content/public/common/referrer.h" | 22 #include "content/public/common/referrer.h" |
| 26 #include "ui/gfx/size.h" | 23 #include "ui/gfx/size.h" |
| 27 #include "url/gurl.h" | 24 #include "url/gurl.h" |
| 28 | 25 |
| 29 using base::TimeDelta; | 26 using base::TimeDelta; |
| 30 using base::TimeTicks; | 27 using base::TimeTicks; |
| 31 using content::RenderViewHost; | 28 using content::RenderViewHost; |
| 32 using content::SessionStorageNamespace; | 29 using content::SessionStorageNamespace; |
| 33 | 30 |
| 34 namespace prerender { | |
| 35 | |
| 36 namespace { | 31 namespace { |
| 37 | 32 |
| 38 bool ShouldStartRelNextPrerenders() { | |
| 39 const std::string experiment_name = | |
| 40 base::FieldTrialList::FindFullName("PrerenderRelNextTrial"); | |
| 41 | |
| 42 return experiment_name.find("Yes") != std::string::npos; | |
| 43 } | |
| 44 | |
| 45 bool ShouldStartPrerender(uint32 rel_types) { | |
| 46 const bool should_start_rel_next_prerenders = | |
| 47 ShouldStartRelNextPrerenders(); | |
| 48 | |
| 49 if (rel_types & PrerenderRelTypePrerender) { | |
| 50 return true; | |
| 51 } else if (should_start_rel_next_prerenders && | |
| 52 (rel_types & PrerenderRelTypeNext) == PrerenderRelTypeNext) { | |
| 53 return true; | |
| 54 } | |
| 55 return false; | |
| 56 } | |
| 57 | |
| 58 void Send(int child_id, IPC::Message* raw_message) { | 33 void Send(int child_id, IPC::Message* raw_message) { |
| 59 using content::RenderProcessHost; | 34 using content::RenderProcessHost; |
| 60 scoped_ptr<IPC::Message> own_message(raw_message); | 35 scoped_ptr<IPC::Message> own_message(raw_message); |
| 61 | 36 |
| 62 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); | 37 RenderProcessHost* render_process_host = RenderProcessHost::FromID(child_id); |
| 63 if (!render_process_host) | 38 if (!render_process_host) |
| 64 return; | 39 return; |
| 65 render_process_host->Send(own_message.release()); | 40 render_process_host->Send(own_message.release()); |
| 66 } | 41 } |
| 67 | 42 |
| 68 } // namespace | 43 } // namespace |
| 69 | 44 |
| 45 namespace prerender { |
| 46 |
| 70 // Helper class to implement PrerenderContents::Observer and watch prerenders | 47 // Helper class to implement PrerenderContents::Observer and watch prerenders |
| 71 // which launch other prerenders. | 48 // which launch other prerenders. |
| 72 class PrerenderLinkManager::PendingPrerenderManager | 49 class PrerenderLinkManager::PendingPrerenderManager |
| 73 : public PrerenderContents::Observer { | 50 : public PrerenderContents::Observer { |
| 74 public: | 51 public: |
| 75 explicit PendingPrerenderManager(PrerenderLinkManager* link_manager) | 52 explicit PendingPrerenderManager(PrerenderLinkManager* link_manager) |
| 76 : link_manager_(link_manager) {} | 53 : link_manager_(link_manager) {} |
| 77 | 54 |
| 78 virtual ~PendingPrerenderManager() { | 55 virtual ~PendingPrerenderManager() { |
| 79 DCHECK(observed_launchers_.empty()); | 56 DCHECK(observed_launchers_.empty()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 << "PrerenderManager."; | 102 << "PrerenderManager."; |
| 126 delete i->handle; | 103 delete i->handle; |
| 127 i->handle = 0; | 104 i->handle = 0; |
| 128 } | 105 } |
| 129 } | 106 } |
| 130 } | 107 } |
| 131 | 108 |
| 132 void PrerenderLinkManager::OnAddPrerender(int launcher_child_id, | 109 void PrerenderLinkManager::OnAddPrerender(int launcher_child_id, |
| 133 int prerender_id, | 110 int prerender_id, |
| 134 const GURL& url, | 111 const GURL& url, |
| 135 uint32 rel_types, | |
| 136 const content::Referrer& referrer, | 112 const content::Referrer& referrer, |
| 137 const gfx::Size& size, | 113 const gfx::Size& size, |
| 138 int render_view_route_id) { | 114 int render_view_route_id) { |
| 139 DCHECK_EQ(static_cast<LinkPrerender*>(NULL), | 115 DCHECK_EQ(static_cast<LinkPrerender*>(NULL), |
| 140 FindByLauncherChildIdAndPrerenderId(launcher_child_id, | 116 FindByLauncherChildIdAndPrerenderId(launcher_child_id, |
| 141 prerender_id)); | 117 prerender_id)); |
| 142 content::RenderProcessHost* rph = | 118 content::RenderProcessHost* rph = |
| 143 content::RenderProcessHost::FromID(launcher_child_id); | 119 content::RenderProcessHost::FromID(launcher_child_id); |
| 144 // Guests inside <webview> do not support cross-process navigation and so we | 120 // Guests inside <webview> do not support cross-process navigation and so we |
| 145 // do not allow guests to prerender content. | 121 // do not allow guests to prerender content. |
| 146 if (rph && rph->IsGuest()) | 122 if (rph && rph->IsGuest()) |
| 147 return; | 123 return; |
| 148 | 124 |
| 149 // Check if the launcher is itself an unswapped prerender. | 125 // Check if the launcher is itself an unswapped prerender. |
| 150 PrerenderContents* prerender_contents = | 126 PrerenderContents* prerender_contents = |
| 151 manager_->GetPrerenderContentsForRoute(launcher_child_id, | 127 manager_->GetPrerenderContentsForRoute(launcher_child_id, |
| 152 render_view_route_id); | 128 render_view_route_id); |
| 153 if (prerender_contents && | 129 if (prerender_contents && |
| 154 prerender_contents->final_status() != FINAL_STATUS_MAX) { | 130 prerender_contents->final_status() != FINAL_STATUS_MAX) { |
| 155 // The launcher is a prerender about to be destroyed asynchronously, but | 131 // The launcher is a prerender about to be destroyed asynchronously, but |
| 156 // its AddLinkRelPrerender message raced with shutdown. Ignore it. | 132 // its AddLinkRelPrerender message raced with shutdown. Ignore it. |
| 157 DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status()); | 133 DCHECK_NE(FINAL_STATUS_USED, prerender_contents->final_status()); |
| 158 return; | 134 return; |
| 159 } | 135 } |
| 160 | 136 |
| 161 LinkPrerender | 137 LinkPrerender |
| 162 prerender(launcher_child_id, prerender_id, url, rel_types, referrer, size, | 138 prerender(launcher_child_id, prerender_id, url, referrer, size, |
| 163 render_view_route_id, manager_->GetCurrentTimeTicks(), | 139 render_view_route_id, manager_->GetCurrentTimeTicks(), |
| 164 prerender_contents); | 140 prerender_contents); |
| 165 prerenders_.push_back(prerender); | 141 prerenders_.push_back(prerender); |
| 166 if (prerender_contents) | 142 if (prerender_contents) |
| 167 pending_prerender_manager_->ObserveLauncher(prerender_contents); | 143 pending_prerender_manager_->ObserveLauncher(prerender_contents); |
| 168 else | 144 else |
| 169 StartPrerenders(); | 145 StartPrerenders(); |
| 170 } | 146 } |
| 171 | 147 |
| 172 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { | 148 void PrerenderLinkManager::OnCancelPrerender(int child_id, int prerender_id) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 213 const size_t running_prerender_count = CountRunningPrerenders(); | 189 const size_t running_prerender_count = CountRunningPrerenders(); |
| 214 OnAbandonPrerender(child_id, it->prerender_id); | 190 OnAbandonPrerender(child_id, it->prerender_id); |
| 215 DCHECK_EQ(running_prerender_count, CountRunningPrerenders()); | 191 DCHECK_EQ(running_prerender_count, CountRunningPrerenders()); |
| 216 } | 192 } |
| 217 } | 193 } |
| 218 | 194 |
| 219 PrerenderLinkManager::LinkPrerender::LinkPrerender( | 195 PrerenderLinkManager::LinkPrerender::LinkPrerender( |
| 220 int launcher_child_id, | 196 int launcher_child_id, |
| 221 int prerender_id, | 197 int prerender_id, |
| 222 const GURL& url, | 198 const GURL& url, |
| 223 uint32 rel_types, | |
| 224 const content::Referrer& referrer, | 199 const content::Referrer& referrer, |
| 225 const gfx::Size& size, | 200 const gfx::Size& size, |
| 226 int render_view_route_id, | 201 int render_view_route_id, |
| 227 TimeTicks creation_time, | 202 TimeTicks creation_time, |
| 228 PrerenderContents* deferred_launcher) | 203 PrerenderContents* deferred_launcher) |
| 229 : launcher_child_id(launcher_child_id), | 204 : launcher_child_id(launcher_child_id), |
| 230 prerender_id(prerender_id), | 205 prerender_id(prerender_id), |
| 231 url(url), | 206 url(url), |
| 232 rel_types(rel_types), | |
| 233 referrer(referrer), | 207 referrer(referrer), |
| 234 size(size), | 208 size(size), |
| 235 render_view_route_id(render_view_route_id), | 209 render_view_route_id(render_view_route_id), |
| 236 creation_time(creation_time), | 210 creation_time(creation_time), |
| 237 deferred_launcher(deferred_launcher), | 211 deferred_launcher(deferred_launcher), |
| 238 handle(NULL), | 212 handle(NULL), |
| 239 is_match_complete_replacement(false), | 213 is_match_complete_replacement(false), |
| 240 has_been_abandoned(false) { | 214 has_been_abandoned(false) { |
| 241 } | 215 } |
| 242 | 216 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 // an abandoned prerender to make room? | 307 // an abandoned prerender to make room? |
| 334 if (!abandoned_prerenders.empty()) { | 308 if (!abandoned_prerenders.empty()) { |
| 335 CancelPrerender(abandoned_prerenders.front()); | 309 CancelPrerender(abandoned_prerenders.front()); |
| 336 --total_started_prerender_count; | 310 --total_started_prerender_count; |
| 337 abandoned_prerenders.pop_front(); | 311 abandoned_prerenders.pop_front(); |
| 338 } else { | 312 } else { |
| 339 return; | 313 return; |
| 340 } | 314 } |
| 341 } | 315 } |
| 342 | 316 |
| 343 if (!ShouldStartPrerender((*i)->rel_types)) { | |
| 344 prerenders_.erase(*i); | |
| 345 continue; | |
| 346 } | |
| 347 | |
| 348 PrerenderHandle* handle = manager_->AddPrerenderFromLinkRelPrerender( | 317 PrerenderHandle* handle = manager_->AddPrerenderFromLinkRelPrerender( |
| 349 (*i)->launcher_child_id, (*i)->render_view_route_id, | 318 (*i)->launcher_child_id, (*i)->render_view_route_id, |
| 350 (*i)->url, (*i)->referrer, (*i)->size); | 319 (*i)->url, (*i)->referrer, (*i)->size); |
| 351 if (!handle) { | 320 if (!handle) { |
| 352 // This prerender couldn't be launched, it's gone. | 321 // This prerender couldn't be launched, it's gone. |
| 353 prerenders_.erase(*i); | 322 prerenders_.erase(*i); |
| 354 continue; | 323 continue; |
| 355 } | 324 } |
| 356 | 325 |
| 357 // We have successfully started a new prerender. | 326 // We have successfully started a new prerender. |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 DCHECK(!prerender->is_match_complete_replacement); | 464 DCHECK(!prerender->is_match_complete_replacement); |
| 496 prerender->is_match_complete_replacement = true; | 465 prerender->is_match_complete_replacement = true; |
| 497 Send(prerender->launcher_child_id, | 466 Send(prerender->launcher_child_id, |
| 498 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id)); | 467 new PrerenderMsg_OnPrerenderStop(prerender->prerender_id)); |
| 499 // Do not call RemovePrerender here. The replacement needs to stay connected | 468 // Do not call RemovePrerender here. The replacement needs to stay connected |
| 500 // to the HTMLLinkElement in the renderer so it notices renderer-triggered | 469 // to the HTMLLinkElement in the renderer so it notices renderer-triggered |
| 501 // cancelations. | 470 // cancelations. |
| 502 } | 471 } |
| 503 | 472 |
| 504 } // namespace prerender | 473 } // namespace prerender |
| OLD | NEW |