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